|
|
@@ -1,140 +0,0 @@
|
|
|
-package protocol
|
|
|
-
|
|
|
-import (
|
|
|
- "crypto/aes"
|
|
|
- "crypto/cipher"
|
|
|
- "encoding/binary"
|
|
|
- "hash/fnv"
|
|
|
- "time"
|
|
|
-
|
|
|
- "github.com/v2ray/v2ray-core/common/errors"
|
|
|
- "github.com/v2ray/v2ray-core/common/log"
|
|
|
- v2net "github.com/v2ray/v2ray-core/common/net"
|
|
|
- "github.com/v2ray/v2ray-core/proxy/vmess/protocol/user"
|
|
|
-)
|
|
|
-
|
|
|
-type VMessUDP struct {
|
|
|
- user user.ID
|
|
|
- version byte
|
|
|
- address v2net.Address
|
|
|
- data []byte
|
|
|
-}
|
|
|
-
|
|
|
-func (message *VMessUDP) ToPacket() v2net.Packet {
|
|
|
- dest := v2net.NewUDPDestination(message.address)
|
|
|
- return v2net.NewPacket(dest, message.data, false)
|
|
|
-}
|
|
|
-
|
|
|
-func ReadVMessUDP(buffer []byte, userset user.UserSet) (*VMessUDP, error) {
|
|
|
- userHash := buffer[:user.IDBytesLen]
|
|
|
- userId, timeSec, valid := userset.GetUser(userHash)
|
|
|
- if !valid {
|
|
|
- return nil, errors.NewAuthenticationError(userHash)
|
|
|
- }
|
|
|
-
|
|
|
- buffer = buffer[user.IDBytesLen:]
|
|
|
- aesCipher, err := aes.NewCipher(userId.CmdKey())
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec))
|
|
|
- aesStream.XORKeyStream(buffer, buffer)
|
|
|
-
|
|
|
- fnvHash := binary.BigEndian.Uint32(buffer[:4])
|
|
|
- fnv1a := fnv.New32a()
|
|
|
- fnv1a.Write(buffer[4:])
|
|
|
- fnvHashActual := fnv1a.Sum32()
|
|
|
-
|
|
|
- if fnvHash != fnvHashActual {
|
|
|
- log.Warning("Unexpected fhv hash %d, should be %d", fnvHashActual, fnvHash)
|
|
|
- return nil, errors.NewCorruptedPacketError()
|
|
|
- }
|
|
|
-
|
|
|
- buffer = buffer[4:]
|
|
|
-
|
|
|
- vmess := &VMessUDP{
|
|
|
- user: *userId,
|
|
|
- version: buffer[0],
|
|
|
- }
|
|
|
-
|
|
|
- // buffer[1] is reserved
|
|
|
-
|
|
|
- port := binary.BigEndian.Uint16(buffer[2:4])
|
|
|
- addrType := buffer[4]
|
|
|
- var address v2net.Address
|
|
|
- switch addrType {
|
|
|
- case addrTypeIPv4:
|
|
|
- address = v2net.IPAddress(buffer[5:9], port)
|
|
|
- buffer = buffer[9:]
|
|
|
- case addrTypeIPv6:
|
|
|
- address = v2net.IPAddress(buffer[5:21], port)
|
|
|
- buffer = buffer[21:]
|
|
|
- case addrTypeDomain:
|
|
|
- domainLength := buffer[5]
|
|
|
- domain := string(buffer[6 : 6+domainLength])
|
|
|
- address = v2net.DomainAddress(domain, port)
|
|
|
- buffer = buffer[6+domainLength:]
|
|
|
- default:
|
|
|
- log.Warning("Unexpected address type %d", addrType)
|
|
|
- return nil, errors.NewCorruptedPacketError()
|
|
|
- }
|
|
|
-
|
|
|
- vmess.address = address
|
|
|
- vmess.data = buffer
|
|
|
-
|
|
|
- return vmess, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (vmess *VMessUDP) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer []byte) []byte {
|
|
|
- if buffer == nil {
|
|
|
- buffer = make([]byte, 0, 2*1024)
|
|
|
- }
|
|
|
-
|
|
|
- counter := randomRangeInt64(time.Now().UTC().Unix(), 30)
|
|
|
- hash := idHash.Hash(vmess.user.Bytes[:], counter)
|
|
|
-
|
|
|
- buffer = append(buffer, hash...)
|
|
|
- encryptBegin := 16
|
|
|
-
|
|
|
- // Placeholder for fnv1a hash
|
|
|
- buffer = append(buffer, byte(0), byte(0), byte(0), byte(0))
|
|
|
- fnvHash := 16
|
|
|
- fnvHashBegin := 20
|
|
|
-
|
|
|
- buffer = append(buffer, vmess.version)
|
|
|
- buffer = append(buffer, byte(0x00))
|
|
|
- buffer = append(buffer, vmess.address.PortBytes()...)
|
|
|
- switch {
|
|
|
- case vmess.address.IsIPv4():
|
|
|
- buffer = append(buffer, addrTypeIPv4)
|
|
|
- buffer = append(buffer, vmess.address.IP()...)
|
|
|
- case vmess.address.IsIPv6():
|
|
|
- buffer = append(buffer, addrTypeIPv6)
|
|
|
- buffer = append(buffer, vmess.address.IP()...)
|
|
|
- case vmess.address.IsDomain():
|
|
|
- buffer = append(buffer, addrTypeDomain)
|
|
|
- buffer = append(buffer, byte(len(vmess.address.Domain())))
|
|
|
- buffer = append(buffer, []byte(vmess.address.Domain())...)
|
|
|
- }
|
|
|
-
|
|
|
- buffer = append(buffer, vmess.data...)
|
|
|
-
|
|
|
- fnv1a := fnv.New32a()
|
|
|
- fnv1a.Write(buffer[fnvHashBegin:])
|
|
|
- fnvHashValue := fnv1a.Sum32()
|
|
|
-
|
|
|
- buffer[fnvHash] = byte(fnvHashValue >> 24)
|
|
|
- buffer[fnvHash+1] = byte(fnvHashValue >> 16)
|
|
|
- buffer[fnvHash+2] = byte(fnvHashValue >> 8)
|
|
|
- buffer[fnvHash+3] = byte(fnvHashValue)
|
|
|
-
|
|
|
- aesCipher, err := aes.NewCipher(vmess.user.CmdKey())
|
|
|
- if err != nil {
|
|
|
- log.Error("VMess failed to create AES cipher: %v", err)
|
|
|
- return nil
|
|
|
- }
|
|
|
- aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter))
|
|
|
- aesStream.XORKeyStream(buffer[encryptBegin:], buffer[encryptBegin:])
|
|
|
-
|
|
|
- return buffer
|
|
|
-}
|