validator.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. //go:build !confonly
  2. // +build !confonly
  3. package vmess
  4. import (
  5. "crypto/hmac"
  6. "crypto/sha256"
  7. "hash/crc64"
  8. "strings"
  9. "sync"
  10. "sync/atomic"
  11. "time"
  12. "github.com/v2fly/v2ray-core/v4/common"
  13. "github.com/v2fly/v2ray-core/v4/common/dice"
  14. "github.com/v2fly/v2ray-core/v4/common/protocol"
  15. "github.com/v2fly/v2ray-core/v4/common/serial"
  16. "github.com/v2fly/v2ray-core/v4/common/task"
  17. "github.com/v2fly/v2ray-core/v4/proxy/vmess/aead"
  18. )
  19. const (
  20. updateInterval = 10 * time.Second
  21. cacheDurationSec = 120
  22. )
  23. type user struct {
  24. user protocol.MemoryUser
  25. lastSec protocol.Timestamp
  26. }
  27. // TimedUserValidator is a user Validator based on time.
  28. type TimedUserValidator struct {
  29. sync.RWMutex
  30. users []*user
  31. userHash map[[16]byte]indexTimePair
  32. hasher protocol.IDHash
  33. baseTime protocol.Timestamp
  34. task *task.Periodic
  35. behaviorSeed uint64
  36. behaviorFused bool
  37. aeadDecoderHolder *aead.AuthIDDecoderHolder
  38. legacyWarnShown bool
  39. }
  40. type indexTimePair struct {
  41. user *user
  42. timeInc uint32
  43. taintedFuse *uint32
  44. }
  45. // NewTimedUserValidator creates a new TimedUserValidator.
  46. func NewTimedUserValidator(hasher protocol.IDHash) *TimedUserValidator {
  47. tuv := &TimedUserValidator{
  48. users: make([]*user, 0, 16),
  49. userHash: make(map[[16]byte]indexTimePair, 1024),
  50. hasher: hasher,
  51. baseTime: protocol.Timestamp(time.Now().Unix() - cacheDurationSec*2),
  52. aeadDecoderHolder: aead.NewAuthIDDecoderHolder(),
  53. }
  54. tuv.task = &task.Periodic{
  55. Interval: updateInterval,
  56. Execute: func() error {
  57. tuv.updateUserHash()
  58. return nil
  59. },
  60. }
  61. common.Must(tuv.task.Start())
  62. return tuv
  63. }
  64. func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, user *user) {
  65. var hashValue [16]byte
  66. genEndSec := nowSec + cacheDurationSec
  67. genHashForID := func(id *protocol.ID) {
  68. idHash := v.hasher(id.Bytes())
  69. genBeginSec := user.lastSec
  70. if genBeginSec < nowSec-cacheDurationSec {
  71. genBeginSec = nowSec - cacheDurationSec
  72. }
  73. for ts := genBeginSec; ts <= genEndSec; ts++ {
  74. common.Must2(serial.WriteUint64(idHash, uint64(ts)))
  75. idHash.Sum(hashValue[:0])
  76. idHash.Reset()
  77. v.userHash[hashValue] = indexTimePair{
  78. user: user,
  79. timeInc: uint32(ts - v.baseTime),
  80. taintedFuse: new(uint32),
  81. }
  82. }
  83. }
  84. account := user.user.Account.(*MemoryAccount)
  85. genHashForID(account.ID)
  86. for _, id := range account.AlterIDs {
  87. genHashForID(id)
  88. }
  89. user.lastSec = genEndSec
  90. }
  91. func (v *TimedUserValidator) removeExpiredHashes(expire uint32) {
  92. for key, pair := range v.userHash {
  93. if pair.timeInc < expire {
  94. delete(v.userHash, key)
  95. }
  96. }
  97. }
  98. func (v *TimedUserValidator) updateUserHash() {
  99. now := time.Now()
  100. nowSec := protocol.Timestamp(now.Unix())
  101. v.Lock()
  102. defer v.Unlock()
  103. for _, user := range v.users {
  104. v.generateNewHashes(nowSec, user)
  105. }
  106. expire := protocol.Timestamp(now.Unix() - cacheDurationSec)
  107. if expire > v.baseTime {
  108. v.removeExpiredHashes(uint32(expire - v.baseTime))
  109. }
  110. }
  111. func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error {
  112. v.Lock()
  113. defer v.Unlock()
  114. nowSec := time.Now().Unix()
  115. uu := &user{
  116. user: *u,
  117. lastSec: protocol.Timestamp(nowSec - cacheDurationSec),
  118. }
  119. v.users = append(v.users, uu)
  120. v.generateNewHashes(protocol.Timestamp(nowSec), uu)
  121. account := uu.user.Account.(*MemoryAccount)
  122. if !v.behaviorFused {
  123. hashkdf := hmac.New(sha256.New, []byte("VMESSBSKDF"))
  124. hashkdf.Write(account.ID.Bytes())
  125. v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), hashkdf.Sum(nil))
  126. }
  127. var cmdkeyfl [16]byte
  128. copy(cmdkeyfl[:], account.ID.CmdKey())
  129. v.aeadDecoderHolder.AddUser(cmdkeyfl, u)
  130. return nil
  131. }
  132. func (v *TimedUserValidator) Get(userHash []byte) (*protocol.MemoryUser, protocol.Timestamp, bool, error) {
  133. v.RLock()
  134. defer v.RUnlock()
  135. v.behaviorFused = true
  136. var fixedSizeHash [16]byte
  137. copy(fixedSizeHash[:], userHash)
  138. pair, found := v.userHash[fixedSizeHash]
  139. if found {
  140. user := pair.user.user
  141. if atomic.LoadUint32(pair.taintedFuse) == 0 {
  142. return &user, protocol.Timestamp(pair.timeInc) + v.baseTime, true, nil
  143. }
  144. return nil, 0, false, ErrTainted
  145. }
  146. return nil, 0, false, ErrNotFound
  147. }
  148. func (v *TimedUserValidator) GetAEAD(userHash []byte) (*protocol.MemoryUser, bool, error) {
  149. v.RLock()
  150. defer v.RUnlock()
  151. var userHashFL [16]byte
  152. copy(userHashFL[:], userHash)
  153. userd, err := v.aeadDecoderHolder.Match(userHashFL)
  154. if err != nil {
  155. return nil, false, err
  156. }
  157. return userd.(*protocol.MemoryUser), true, err
  158. }
  159. func (v *TimedUserValidator) Remove(email string) bool {
  160. v.Lock()
  161. defer v.Unlock()
  162. email = strings.ToLower(email)
  163. idx := -1
  164. for i, u := range v.users {
  165. if strings.EqualFold(u.user.Email, email) {
  166. idx = i
  167. var cmdkeyfl [16]byte
  168. copy(cmdkeyfl[:], u.user.Account.(*MemoryAccount).ID.CmdKey())
  169. v.aeadDecoderHolder.RemoveUser(cmdkeyfl)
  170. break
  171. }
  172. }
  173. if idx == -1 {
  174. return false
  175. }
  176. ulen := len(v.users)
  177. v.users[idx] = v.users[ulen-1]
  178. v.users[ulen-1] = nil
  179. v.users = v.users[:ulen-1]
  180. return true
  181. }
  182. // Close implements common.Closable.
  183. func (v *TimedUserValidator) Close() error {
  184. return v.task.Close()
  185. }
  186. func (v *TimedUserValidator) GetBehaviorSeed() uint64 {
  187. v.Lock()
  188. defer v.Unlock()
  189. v.behaviorFused = true
  190. if v.behaviorSeed == 0 {
  191. v.behaviorSeed = dice.RollUint64()
  192. }
  193. return v.behaviorSeed
  194. }
  195. func (v *TimedUserValidator) BurnTaintFuse(userHash []byte) error {
  196. v.RLock()
  197. defer v.RUnlock()
  198. var userHashFL [16]byte
  199. copy(userHashFL[:], userHash)
  200. pair, found := v.userHash[userHashFL]
  201. if found {
  202. if atomic.CompareAndSwapUint32(pair.taintedFuse, 0, 1) {
  203. return nil
  204. }
  205. return ErrTainted
  206. }
  207. return ErrNotFound
  208. }
  209. /* ShouldShowLegacyWarn will return whether a Legacy Warning should be shown
  210. Not guaranteed to only return true once for every inbound, but it is okay.
  211. */
  212. func (v *TimedUserValidator) ShouldShowLegacyWarn() bool {
  213. if v.legacyWarnShown {
  214. return false
  215. }
  216. v.legacyWarnShown = true
  217. return true
  218. }
  219. var ErrNotFound = newError("Not Found")
  220. var ErrTainted = newError("ErrTainted")