udp.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package protocol
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "encoding/binary"
  6. "hash/fnv"
  7. "time"
  8. "github.com/v2ray/v2ray-core/common/errors"
  9. "github.com/v2ray/v2ray-core/common/log"
  10. v2net "github.com/v2ray/v2ray-core/common/net"
  11. "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user"
  12. )
  13. type VMessUDP struct {
  14. user user.ID
  15. version byte
  16. token uint16
  17. address v2net.Address
  18. data []byte
  19. }
  20. func ReadVMessUDP(buffer []byte, userset user.UserSet) (*VMessUDP, error) {
  21. userHash := buffer[:user.IDBytesLen]
  22. userId, timeSec, valid := userset.GetUser(userHash)
  23. if !valid {
  24. return nil, errors.NewAuthenticationError(userHash)
  25. }
  26. buffer = buffer[user.IDBytesLen:]
  27. aesCipher, err := aes.NewCipher(userId.CmdKey())
  28. if err != nil {
  29. return nil, err
  30. }
  31. aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec))
  32. aesStream.XORKeyStream(buffer, buffer)
  33. fnvHash := binary.BigEndian.Uint32(buffer[:4])
  34. fnv1a := fnv.New32a()
  35. fnv1a.Write(buffer[4:])
  36. fnvHashActual := fnv1a.Sum32()
  37. if fnvHash != fnvHashActual {
  38. log.Warning("Unexpected fhv hash %d, should be %d", fnvHashActual, fnvHash)
  39. return nil, errors.NewCorruptedPacketError()
  40. }
  41. buffer = buffer[4:]
  42. vmess := &VMessUDP{
  43. user: *userId,
  44. version: buffer[0],
  45. token: binary.BigEndian.Uint16(buffer[1:3]),
  46. }
  47. // buffer[3] is reserved
  48. port := binary.BigEndian.Uint16(buffer[4:6])
  49. addrType := buffer[6]
  50. var address v2net.Address
  51. switch addrType {
  52. case addrTypeIPv4:
  53. address = v2net.IPAddress(buffer[7:11], port)
  54. buffer = buffer[11:]
  55. case addrTypeIPv6:
  56. address = v2net.IPAddress(buffer[7:23], port)
  57. buffer = buffer[23:]
  58. case addrTypeDomain:
  59. domainLength := buffer[7]
  60. domain := string(buffer[8 : 8+domainLength])
  61. address = v2net.DomainAddress(domain, port)
  62. buffer = buffer[8+domainLength:]
  63. default:
  64. log.Warning("Unexpected address type %d", addrType)
  65. return nil, errors.NewCorruptedPacketError()
  66. }
  67. vmess.address = address
  68. vmess.data = buffer
  69. return vmess, nil
  70. }
  71. func (vmess *VMessUDP) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer []byte) []byte {
  72. if buffer == nil {
  73. buffer = make([]byte, 0, 2*1024)
  74. }
  75. counter := randomRangeInt64(time.Now().UTC().Unix(), 30)
  76. hash := idHash.Hash(vmess.user.Bytes[:], counter)
  77. buffer = append(buffer, hash...)
  78. encryptBegin := 16
  79. // Placeholder for fnv1a hash
  80. buffer = append(buffer, byte(0), byte(0), byte(0), byte(0))
  81. fnvHash := 16
  82. fnvHashBegin := 20
  83. buffer = append(buffer, vmess.version)
  84. buffer = append(buffer, byte(vmess.token>>8), byte(vmess.token))
  85. buffer = append(buffer, byte(0x00))
  86. buffer = append(buffer, vmess.address.PortBytes()...)
  87. switch {
  88. case vmess.address.IsIPv4():
  89. buffer = append(buffer, addrTypeIPv4)
  90. buffer = append(buffer, vmess.address.IP()...)
  91. case vmess.address.IsIPv6():
  92. buffer = append(buffer, addrTypeIPv6)
  93. buffer = append(buffer, vmess.address.IP()...)
  94. case vmess.address.IsDomain():
  95. buffer = append(buffer, addrTypeDomain)
  96. buffer = append(buffer, byte(len(vmess.address.Domain())))
  97. buffer = append(buffer, []byte(vmess.address.Domain())...)
  98. }
  99. buffer = append(buffer, vmess.data...)
  100. fnv1a := fnv.New32a()
  101. fnv1a.Write(buffer[fnvHashBegin:])
  102. fnvHashValue := fnv1a.Sum32()
  103. buffer[fnvHash] = byte(fnvHashValue >> 24)
  104. buffer[fnvHash+1] = byte(fnvHashValue >> 16)
  105. buffer[fnvHash+2] = byte(fnvHashValue >> 8)
  106. buffer[fnvHash+3] = byte(fnvHashValue)
  107. aesCipher, err := aes.NewCipher(vmess.user.CmdKey())
  108. if err != nil {
  109. log.Error("VMess failed to create AES cipher: %v", err)
  110. return nil
  111. }
  112. aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter))
  113. aesStream.XORKeyStream(buffer[encryptBegin:], buffer[encryptBegin:])
  114. return buffer
  115. }