|  | @@ -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
 | 
	
		
			
				|  |  | -}
 |