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