Пример #1
0
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],
		token:   binary.BigEndian.Uint16(buffer[1:3]),
	}

	// buffer[3] is reserved

	port := binary.BigEndian.Uint16(buffer[4:6])
	addrType := buffer[6]
	var address v2net.Address
	switch addrType {
	case addrTypeIPv4:
		address = v2net.IPAddress(buffer[7:11], port)
		buffer = buffer[11:]
	case addrTypeIPv6:
		address = v2net.IPAddress(buffer[7:23], port)
		buffer = buffer[23:]
	case addrTypeDomain:
		domainLength := buffer[7]
		domain := string(buffer[8 : 8+domainLength])
		address = v2net.DomainAddress(domain, port)
		buffer = buffer[8+domainLength:]
	default:
		log.Warning("Unexpected address type %d", addrType)
		return nil, errors.NewCorruptedPacketError()
	}

	vmess.address = address
	vmess.data = buffer

	return vmess, nil
}
Пример #2
0
func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange) ([]byte, error) {
	buffer := make([]byte, 0, 300)

	counter := randomRangeInt64(time.Now().UTC().Unix(), 30)
	hash := idHash.Hash(request.UserId.Bytes, counter)

	log.Debug("Writing userhash: %v", hash)
	buffer = append(buffer, hash...)

	encryptionBegin := len(buffer)

	randomLength := mrand.Intn(32) + 1
	randomContent := make([]byte, randomLength)
	_, err := rand.Read(randomContent)
	if err != nil {
		return nil, err
	}
	buffer = append(buffer, byte(randomLength))
	buffer = append(buffer, randomContent...)

	buffer = append(buffer, request.Version)
	buffer = append(buffer, request.RequestIV[:]...)
	buffer = append(buffer, request.RequestKey[:]...)
	buffer = append(buffer, request.ResponseHeader[:]...)
	buffer = append(buffer, request.Command)
	buffer = append(buffer, request.Address.PortBytes()...)

	switch {
	case request.Address.IsIPv4():
		buffer = append(buffer, addrTypeIPv4)
		buffer = append(buffer, request.Address.IP()...)
	case request.Address.IsIPv6():
		buffer = append(buffer, addrTypeIPv6)
		buffer = append(buffer, request.Address.IP()...)
	case request.Address.IsDomain():
		buffer = append(buffer, addrTypeDomain)
		buffer = append(buffer, byte(len(request.Address.Domain())))
		buffer = append(buffer, []byte(request.Address.Domain())...)
	}

	paddingLength := mrand.Intn(32) + 1
	paddingBuffer := make([]byte, paddingLength)
	_, err = rand.Read(paddingBuffer)
	if err != nil {
		return nil, err
	}
	buffer = append(buffer, byte(paddingLength))
	buffer = append(buffer, paddingBuffer...)
	encryptionEnd := len(buffer)

	aesCipher, err := aes.NewCipher(request.UserId.CmdKey())
	if err != nil {
		return nil, err
	}
	aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter))
	aesStream.XORKeyStream(buffer[encryptionBegin:encryptionEnd], buffer[encryptionBegin:encryptionEnd])

	return buffer, nil
}
Пример #3
0
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(vmess.token>>8), byte(vmess.token))
	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
}
Пример #4
0
// ToBytes returns a VMessRequest in the form of byte array.
func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer []byte) ([]byte, error) {
	if buffer == nil {
		buffer = make([]byte, 0, 300)
	}

	counter := randomRangeInt64(time.Now().UTC().Unix(), 30)
	hash := idHash.Hash(request.UserId.Bytes[:], counter)

	log.Debug("Writing userhash: %v", hash)
	buffer = append(buffer, hash...)

	encryptionBegin := len(buffer)

	buffer = append(buffer, request.Version)
	buffer = append(buffer, request.RequestIV[:]...)
	buffer = append(buffer, request.RequestKey[:]...)
	buffer = append(buffer, request.ResponseHeader[:]...)
	buffer = append(buffer, request.Command)
	buffer = append(buffer, request.Address.PortBytes()...)

	switch {
	case request.Address.IsIPv4():
		buffer = append(buffer, addrTypeIPv4)
		buffer = append(buffer, request.Address.IP()...)
	case request.Address.IsIPv6():
		buffer = append(buffer, addrTypeIPv6)
		buffer = append(buffer, request.Address.IP()...)
	case request.Address.IsDomain():
		buffer = append(buffer, addrTypeDomain)
		buffer = append(buffer, byte(len(request.Address.Domain())))
		buffer = append(buffer, []byte(request.Address.Domain())...)
	}

	encryptionEnd := len(buffer)

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer[encryptionBegin:encryptionEnd])

	fnvHash := fnv1a.Sum32()
	buffer = append(buffer, byte(fnvHash>>24))
	buffer = append(buffer, byte(fnvHash>>16))
	buffer = append(buffer, byte(fnvHash>>8))
	buffer = append(buffer, byte(fnvHash))
	encryptionEnd += 4

	aesCipher, err := aes.NewCipher(request.UserId.CmdKey())
	if err != nil {
		return nil, err
	}
	aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter))
	aesStream.XORKeyStream(buffer[encryptionBegin:encryptionEnd], buffer[encryptionBegin:encryptionEnd])

	return buffer, nil
}
Пример #5
0
// ToBytes returns a VMessRequest in the form of byte array.
func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer *alloc.Buffer) (*alloc.Buffer, error) {
	if buffer == nil {
		buffer = alloc.NewSmallBuffer().Clear()
	}

	counter := randomRangeInt64(time.Now().UTC().Unix(), 30)
	hash := idHash.Hash(request.UserId.Bytes[:], counter)

	buffer.Append(hash)

	encryptionBegin := buffer.Len()

	buffer.AppendBytes(request.Version)
	buffer.Append(request.RequestIV)
	buffer.Append(request.RequestKey)
	buffer.Append(request.ResponseHeader)
	buffer.AppendBytes(request.Command)
	buffer.Append(request.Address.PortBytes())

	switch {
	case request.Address.IsIPv4():
		buffer.AppendBytes(addrTypeIPv4)
		buffer.Append(request.Address.IP())
	case request.Address.IsIPv6():
		buffer.AppendBytes(addrTypeIPv6)
		buffer.Append(request.Address.IP())
	case request.Address.IsDomain():
		buffer.AppendBytes(addrTypeDomain, byte(len(request.Address.Domain())))
		buffer.Append([]byte(request.Address.Domain()))
	}

	encryptionEnd := buffer.Len()

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer.Value[encryptionBegin:encryptionEnd])

	fnvHash := fnv1a.Sum32()
	buffer.AppendBytes(byte(fnvHash>>24), byte(fnvHash>>16), byte(fnvHash>>8), byte(fnvHash))
	encryptionEnd += 4

	aesCipher, err := aes.NewCipher(request.UserId.CmdKey())
	if err != nil {
		return nil, err
	}
	aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter))
	aesStream.XORKeyStream(buffer.Value[encryptionBegin:encryptionEnd], buffer.Value[encryptionBegin:encryptionEnd])

	return buffer, nil
}
Пример #6
0
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
	buffer := make([]byte, 256)

	nBytes, err := reader.Read(buffer[:user.IDBytesLen])
	if err != nil {
		return nil, err
	}

	log.Debug("Read user hash: %v", buffer[:nBytes])

	userId, timeSec, valid := r.vUserSet.GetUser(buffer[:nBytes])
	if !valid {
		return nil, ErrorInvalidUser
	}

	aesCipher, err := aes.NewCipher(userId.CmdKey())
	if err != nil {
		return nil, err
	}
	aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec))
	decryptor := v2io.NewCryptionReader(aesStream, reader)

	if err != nil {
		return nil, err
	}

	nBytes, err = decryptor.Read(buffer[0:1])
	if err != nil {
		return nil, err
	}

	randomLength := buffer[0]
	if randomLength <= 0 || randomLength > 32 {
		return nil, fmt.Errorf("Unexpected random length %d", randomLength)
	}
	_, err = decryptor.Read(buffer[:randomLength])
	if err != nil {
		return nil, err
	}

	nBytes, err = decryptor.Read(buffer[0:1])
	if err != nil {
		return nil, err
	}

	request := &VMessRequest{
		UserId:  *userId,
		Version: buffer[0],
	}

	if request.Version != Version {
		log.Error("Unknown VMess version %d", request.Version)
		return nil, ErrorInvalidVerion
	}

	// TODO: check number of bytes returned
	_, err = decryptor.Read(request.RequestIV[:])
	if err != nil {
		return nil, err
	}
	_, err = decryptor.Read(request.RequestKey[:])
	if err != nil {
		return nil, err
	}
	_, err = decryptor.Read(request.ResponseHeader[:])
	if err != nil {
		return nil, err
	}
	_, err = decryptor.Read(buffer[0:1])
	if err != nil {
		return nil, err
	}
	request.Command = buffer[0]

	_, err = decryptor.Read(buffer[0:2])
	if err != nil {
		return nil, err
	}
	port := binary.BigEndian.Uint16(buffer[0:2])

	_, err = decryptor.Read(buffer[0:1])
	if err != nil {
		return nil, err
	}
	switch buffer[0] {
	case addrTypeIPv4:
		_, err = decryptor.Read(buffer[1:5])
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer[1:5], port)
	case addrTypeIPv6:
		_, err = decryptor.Read(buffer[1:17])
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer[1:17], port)
	case addrTypeDomain:
		_, err = decryptor.Read(buffer[1:2])
		if err != nil {
			return nil, err
		}
		domainLength := buffer[1]
		_, err = decryptor.Read(buffer[2 : 2+domainLength])
		if err != nil {
			return nil, err
		}
		request.Address = v2net.DomainAddress(string(buffer[2:2+domainLength]), port)
	}
	_, err = decryptor.Read(buffer[0:1])
	if err != nil {
		return nil, err
	}
	randomLength = buffer[0]
	_, err = decryptor.Read(buffer[:randomLength])
	if err != nil {
		return nil, err
	}

	return request, nil
}
Пример #7
0
// Read reads a VMessRequest from a byte stream.
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
	buffer := alloc.NewSmallBuffer()

	nBytes, err := v2net.ReadAllBytes(reader, buffer.Value[:config.IDBytesLen])
	if err != nil {
		return nil, err
	}

	userId, timeSec, valid := r.vUserSet.GetUser(buffer.Value[:nBytes])
	if !valid {
		return nil, proxy.InvalidAuthentication
	}

	aesCipher, err := aes.NewCipher(userId.CmdKey())
	if err != nil {
		return nil, err
	}
	aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec))
	decryptor := v2io.NewCryptionReader(aesStream, reader)

	if err != nil {
		return nil, err
	}

	nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[:41])
	if err != nil {
		return nil, err
	}
	bufferLen := nBytes

	request := &VMessRequest{
		UserId:  *userId,
		Version: buffer.Value[0],
	}

	if request.Version != Version {
		log.Warning("Invalid protocol version %d", request.Version)
		return nil, proxy.InvalidProtocolVersion
	}

	request.RequestIV = buffer.Value[1:17]       // 16 bytes
	request.RequestKey = buffer.Value[17:33]     // 16 bytes
	request.ResponseHeader = buffer.Value[33:37] // 4 bytes
	request.Command = buffer.Value[37]

	port := binary.BigEndian.Uint16(buffer.Value[38:40])

	switch buffer.Value[40] {
	case addrTypeIPv4:
		_, err = v2net.ReadAllBytes(decryptor, buffer.Value[41:45]) // 4 bytes
		bufferLen += 4
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer.Value[41:45], port)
	case addrTypeIPv6:
		_, err = v2net.ReadAllBytes(decryptor, buffer.Value[41:57]) // 16 bytes
		bufferLen += 16
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer.Value[41:57], port)
	case addrTypeDomain:
		_, err = v2net.ReadAllBytes(decryptor, buffer.Value[41:42])
		if err != nil {
			return nil, err
		}
		domainLength := int(buffer.Value[41])
		_, err = v2net.ReadAllBytes(decryptor, buffer.Value[42:42+domainLength])
		if err != nil {
			return nil, err
		}
		bufferLen += 1 + domainLength
		request.Address = v2net.DomainAddress(string(buffer.Value[42:42+domainLength]), port)
	}

	_, err = v2net.ReadAllBytes(decryptor, buffer.Value[bufferLen:bufferLen+4])
	if err != nil {
		return nil, err
	}

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer.Value[:bufferLen])
	actualHash := fnv1a.Sum32()
	expectedHash := binary.BigEndian.Uint32(buffer.Value[bufferLen : bufferLen+4])

	if actualHash != expectedHash {
		return nil, transport.CorruptedPacket
	}

	return request, nil
}
Пример #8
0
// Read reads a VMessRequest from a byte stream.
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
	buffer := make([]byte, 256)

	nBytes, err := reader.Read(buffer[:user.IDBytesLen])
	if err != nil {
		return nil, err
	}

	log.Debug("Read user hash: %v", buffer[:nBytes])

	userId, timeSec, valid := r.vUserSet.GetUser(buffer[:nBytes])
	if !valid {
		return nil, errors.NewAuthenticationError(buffer[:nBytes])
	}

	aesCipher, err := aes.NewCipher(userId.CmdKey())
	if err != nil {
		return nil, err
	}
	aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec))
	decryptor := v2io.NewCryptionReader(aesStream, reader)

	if err != nil {
		return nil, err
	}

	nBytes, err = decryptor.Read(buffer[:41])
	if err != nil {
		return nil, err
	}
	bufferLen := nBytes

	request := &VMessRequest{
		UserId:  *userId,
		Version: buffer[0],
	}

	if request.Version != Version {
		return nil, errors.NewProtocolVersionError(int(request.Version))
	}

	copy(request.RequestIV[:], buffer[1:17])       // 16 bytes
	copy(request.RequestKey[:], buffer[17:33])     // 16 bytes
	copy(request.ResponseHeader[:], buffer[33:37]) // 4 bytes
	request.Command = buffer[37]

	port := binary.BigEndian.Uint16(buffer[38:40])

	switch buffer[40] {
	case addrTypeIPv4:
		_, err = decryptor.Read(buffer[41:45]) // 4 bytes
		bufferLen += 4
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer[41:45], port)
	case addrTypeIPv6:
		_, err = decryptor.Read(buffer[41:57]) // 16 bytes
		bufferLen += 16
		if err != nil {
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer[41:57], port)
	case addrTypeDomain:
		_, err = decryptor.Read(buffer[41:42])
		if err != nil {
			return nil, err
		}
		domainLength := int(buffer[41])
		_, err = decryptor.Read(buffer[42 : 42+domainLength])
		if err != nil {
			return nil, err
		}
		bufferLen += 1 + domainLength
		request.Address = v2net.DomainAddress(string(buffer[42:42+domainLength]), port)
	}

	_, err = decryptor.Read(buffer[bufferLen : bufferLen+4])
	if err != nil {
		return nil, err
	}

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer[:bufferLen])
	actualHash := fnv1a.Sum32()
	expectedHash := binary.BigEndian.Uint32(buffer[bufferLen : bufferLen+4])

	if actualHash != expectedHash {
		return nil, errors.NewCorruptedPacketError()
	}

	return request, nil
}
Пример #9
0
// Read reads a VMessRequest from a byte stream.
func (this *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
	buffer := alloc.NewSmallBuffer()
	defer buffer.Release()

	nBytes, err := v2net.ReadAllBytes(reader, buffer.Value[:vmess.IDBytesLen])
	if err != nil {
		log.Debug("VMess: Failed to read request ID (%d bytes): %v", nBytes, err)
		return nil, err
	}

	userObj, timeSec, valid := this.vUserSet.GetUser(buffer.Value[:nBytes])
	if !valid {
		return nil, proxy.InvalidAuthentication
	}

	aesStream, err := v2crypto.NewAesDecryptionStream(userObj.ID().CmdKey(), user.Int64Hash(timeSec))
	if err != nil {
		log.Debug("VMess: Failed to create AES stream: %v", err)
		return nil, err
	}

	decryptor := v2crypto.NewCryptionReader(aesStream, reader)

	nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[:41])
	if err != nil {
		log.Debug("VMess: Failed to read request header (%d bytes): %v", nBytes, err)
		return nil, err
	}
	bufferLen := nBytes

	request := &VMessRequest{
		User:    userObj,
		Version: buffer.Value[0],
	}

	if request.Version != Version {
		log.Warning("VMess: Invalid protocol version %d", request.Version)
		return nil, proxy.InvalidProtocolVersion
	}

	request.RequestIV = append([]byte(nil), buffer.Value[1:17]...)       // 16 bytes
	request.RequestKey = append([]byte(nil), buffer.Value[17:33]...)     // 16 bytes
	request.ResponseHeader = append([]byte(nil), buffer.Value[33:37]...) // 4 bytes
	request.Command = buffer.Value[37]

	request.Port = v2net.PortFromBytes(buffer.Value[38:40])

	switch buffer.Value[40] {
	case addrTypeIPv4:
		nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[41:45]) // 4 bytes
		bufferLen += 4
		if err != nil {
			log.Debug("VMess: Failed to read target IPv4 (%d bytes): %v", nBytes, err)
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer.Value[41:45])
	case addrTypeIPv6:
		nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[41:57]) // 16 bytes
		bufferLen += 16
		if err != nil {
			log.Debug("VMess: Failed to read target IPv6 (%d bytes): %v", nBytes, err)
			return nil, err
		}
		request.Address = v2net.IPAddress(buffer.Value[41:57])
	case addrTypeDomain:
		nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[41:42])
		if err != nil {
			log.Debug("VMess: Failed to read target domain (%d bytes): %v", nBytes, err)
			return nil, err
		}
		domainLength := int(buffer.Value[41])
		if domainLength == 0 {
			return nil, transport.CorruptedPacket
		}
		nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[42:42+domainLength])
		if err != nil {
			log.Debug("VMess: Failed to read target domain (%d bytes): %v", nBytes, err)
			return nil, err
		}
		bufferLen += 1 + domainLength
		domainBytes := append([]byte(nil), buffer.Value[42:42+domainLength]...)
		request.Address = v2net.DomainAddress(string(domainBytes))
	}

	nBytes, err = v2net.ReadAllBytes(decryptor, buffer.Value[bufferLen:bufferLen+4])
	if err != nil {
		log.Debug("VMess: Failed to read checksum (%d bytes): %v", nBytes, err)
		return nil, err
	}

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer.Value[:bufferLen])
	actualHash := fnv1a.Sum32()
	expectedHash := binary.BigEndian.Uint32(buffer.Value[bufferLen : bufferLen+4])

	if actualHash != expectedHash {
		return nil, transport.CorruptedPacket
	}

	return request, nil
}