func TestVMessSerialization(t *testing.T) { assert := unit.Assert(t) userId, err := core.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") if err != nil { t.Fatal(err) } userSet := mocks.MockUserSet{[]core.ID{}, make(map[string]int), make(map[string]int64)} userSet.AddUser(core.User{userId}) request := new(VMessRequest) request.Version = byte(0x01) request.UserId = userId _, err = rand.Read(request.RequestIV[:]) if err != nil { t.Fatal(err) } _, err = rand.Read(request.RequestKey[:]) if err != nil { t.Fatal(err) } _, err = rand.Read(request.ResponseHeader[:]) if err != nil { t.Fatal(err) } request.Command = byte(0x01) request.Address = v2net.DomainAddress("v2ray.com", 80) buffer := bytes.NewBuffer(make([]byte, 0, 300)) mockTime := int64(1823730) requestWriter := NewVMessRequestWriter(v2hash.NewTimeHash(v2hash.HMACHash{}), func(base int64, delta int) int64 { return mockTime }) err = requestWriter.Write(buffer, request) if err != nil { t.Fatal(err) } userSet.UserHashes[string(buffer.Bytes()[:16])] = 0 userSet.Timestamps[string(buffer.Bytes()[:16])] = mockTime requestReader := NewVMessRequestReader(&userSet) actualRequest, err := requestReader.Read(buffer) if err != nil { t.Fatal(err) } assert.Byte(actualRequest.Version).Named("Version").Equals(byte(0x01)) assert.String(actualRequest.UserId.String).Named("UserId").Equals(request.UserId.String) assert.Bytes(actualRequest.RequestIV[:]).Named("RequestIV").Equals(request.RequestIV[:]) assert.Bytes(actualRequest.RequestKey[:]).Named("RequestKey").Equals(request.RequestKey[:]) assert.Bytes(actualRequest.ResponseHeader[:]).Named("ResponseHeader").Equals(request.ResponseHeader[:]) assert.Byte(actualRequest.Command).Named("Command").Equals(request.Command) assert.String(actualRequest.Address.String()).Named("Address").Equals(request.Address.String()) }
func TestVMessSerialization(t *testing.T) { assert := unit.Assert(t) userId, err := core.UUIDToVID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") if err != nil { t.Fatal(err) } userSet := core.NewVUserSet() userSet.AddUser(core.VUser{userId}) request := new(VMessRequest) request.Version = byte(0x01) request.UserId = userId _, err = rand.Read(request.RequestIV[:]) if err != nil { t.Fatal(err) } _, err = rand.Read(request.RequestKey[:]) if err != nil { t.Fatal(err) } _, err = rand.Read(request.ResponseHeader[:]) if err != nil { t.Fatal(err) } request.Command = byte(0x01) request.Address = v2net.DomainAddress("v2ray.com", 80) buffer := bytes.NewBuffer(make([]byte, 0, 300)) requestWriter := NewVMessRequestWriter() err = requestWriter.Write(buffer, request) if err != nil { t.Fatal(err) } requestReader := NewVMessRequestReader(userSet) actualRequest, err := requestReader.Read(buffer) if err != nil { t.Fatal(err) } assert.Byte(actualRequest.Version).Named("Version").Equals(byte(0x01)) assert.Bytes(actualRequest.UserId[:]).Named("UserId").Equals(request.UserId[:]) assert.Bytes(actualRequest.RequestIV[:]).Named("RequestIV").Equals(request.RequestIV[:]) assert.Bytes(actualRequest.RequestKey[:]).Named("RequestKey").Equals(request.RequestKey[:]) assert.Bytes(actualRequest.ResponseHeader[:]).Named("ResponseHeader").Equals(request.ResponseHeader[:]) assert.Byte(actualRequest.Command).Named("Command").Equals(request.Command) assert.String(actualRequest.Address.String()).Named("Address").Equals(request.Address.String()) }
func (request *Socks5Request) Destination() v2net.VAddress { switch request.AddrType { case AddrTypeIPv4: return v2net.IPAddress(request.IPv4[:], request.Port) case AddrTypeIPv6: return v2net.IPAddress(request.IPv6[:], request.Port) case AddrTypeDomain: return v2net.DomainAddress(request.Domain, request.Port) default: panic("Unknown address type") } }
func (config VNextConfig) ToVNextServer() VNextServer { users := make([]core.VUser, 0, len(config.Users)) for _, user := range config.Users { vuser, err := user.ToVUser() if err != nil { panic(log.Error("Failed to convert %v to VUser.", user)) } users = append(users, vuser) } return VNextServer{ v2net.DomainAddress(config.Address, config.Port), users} }
func BenchmarkVMessRequestWriting(b *testing.B) { userId, _ := core.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") userSet := mocks.MockUserSet{[]core.ID{}, make(map[string]int), make(map[string]int64)} userSet.AddUser(core.User{userId}) request := new(VMessRequest) request.Version = byte(0x01) request.UserId = userId rand.Read(request.RequestIV[:]) rand.Read(request.RequestKey[:]) rand.Read(request.ResponseHeader[:]) request.Command = byte(0x01) request.Address = v2net.DomainAddress("v2ray.com", 80) for i := 0; i < b.N; i++ { request.ToBytes(v2hash.NewTimeHash(v2hash.HMACHash{}), v2math.GenerateRandomInt64InRange) } }
func BenchmarkVMessRequestWriting(b *testing.B) { userId, _ := core.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") userSet := mocks.MockUserSet{[]core.ID{}, make(map[string]int)} userSet.AddUser(core.User{userId}) request := new(VMessRequest) request.Version = byte(0x01) request.UserId = userId rand.Read(request.RequestIV[:]) rand.Read(request.RequestKey[:]) rand.Read(request.ResponseHeader[:]) request.Command = byte(0x01) request.Address = v2net.DomainAddress("v2ray.com", 80) requestWriter := NewVMessRequestWriter() for i := 0; i < b.N; i++ { requestWriter.Write(ioutil.Discard, request) } }
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { buffer := make([]byte, 256) nBytes, err := reader.Read(buffer[:core.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, v2hash.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 }
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { request := new(VMessRequest) buffer := make([]byte, 256) nBytes, err := reader.Read(buffer[0:1]) if err != nil { return nil, err } // TODO: verify version number request.Version = buffer[0] nBytes, err = reader.Read(buffer[:len(request.UserId)]) if err != nil { return nil, err } userId, valid := r.vUserSet.IsValidUserId(buffer[:nBytes]) if !valid { return nil, ErrorInvalidUser } request.UserId = *userId decryptor, err := NewDecryptionReader(reader, userId.Hash([]byte("PWD")), make([]byte, blockSize)) 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 } // 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 }
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { request := new(VMessRequest) buffer := make([]byte, 256) nBytes, err := reader.Read(buffer[0:1]) if err != nil { return nil, err } // TODO: verify version number request.Version = buffer[0] nBytes, err = reader.Read(buffer[:core.IDBytesLen]) if err != nil { return nil, err } userId, valid := r.vUserSet.GetUser(buffer[:nBytes]) if !valid { return nil, ErrorInvalidUser } request.UserId = *userId aesCipher, err := aes.NewCipher(userId.Hash([]byte(CryptoMessage))) if err != nil { return nil, err } aesStream := cipher.NewCFBDecrypter(aesCipher, emptyIV) 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 } // 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 }
func (config VNextConfig) ToVNextServer() VNextServer { return VNextServer{ v2net.DomainAddress(config.Address, config.Port), config.Users} }