func (server *SocksServer) handleSocks4(reader io.Reader, writer io.Writer, auth protocol.Socks4AuthenticationRequest) error { result := protocol.Socks4RequestGranted if auth.Command == protocol.CmdBind { result = protocol.Socks4RequestRejected } socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth.Port, auth.IP[:]) responseBuffer := alloc.NewSmallBuffer().Clear() socks4Response.Write(responseBuffer) writer.Write(responseBuffer.Value) responseBuffer.Release() if result == protocol.Socks4RequestRejected { log.Warning("Unsupported socks 4 command %d", auth.Command) return UnsupportedSocksCommand } dest := v2net.NewTCPDestination(v2net.IPAddress(auth.IP[:], auth.Port)) data, err := v2net.ReadFrom(reader, nil) if err != nil { return err } packet := v2net.NewPacket(dest, data, true) server.transport(reader, writer, packet) return nil }
func TestInsufficientAddressRequest(t *testing.T) { v2testing.Current(t) buffer := alloc.NewSmallBuffer().Clear().AppendBytes(1, 1) _, err := ReadRequest(buffer, nil, false) assert.Error(err).Equals(transport.ErrorCorruptedPacket) buffer = alloc.NewSmallBuffer().Clear().AppendBytes(4, 1) _, err = ReadRequest(buffer, nil, false) assert.Error(err).Equals(transport.ErrorCorruptedPacket) buffer = alloc.NewSmallBuffer().Clear().AppendBytes(3, 255, 1) _, err = ReadRequest(buffer, nil, false) assert.Error(err).Equals(transport.ErrorCorruptedPacket) }
func TestInsufficientPortRequest(t *testing.T) { assert := assert.On(t) buffer := alloc.NewSmallBuffer().Clear().AppendBytes(1, 1, 2, 3, 4, 5) _, err := ReadRequest(buffer, nil, false) assert.Error(err).Equals(transport.ErrCorruptedPacket) }
func TestWrongAddressType(t *testing.T) { v2testing.Current(t) buffer := alloc.NewSmallBuffer().Clear().AppendBytes(5) _, err := ReadRequest(buffer, nil, false) assert.Error(err).Equals(transport.ErrorCorruptedPacket) }
func TestSinglePacket(t *testing.T) { v2testing.Current(t) port := v2nettesting.PickPort() tcpServer := &tcp.Server{ Port: port, MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } _, err := tcpServer.Start() assert.Error(err).IsNil() freedom := &FreedomConnection{} traffic := ray.NewRay() data2Send := "Data to be sent to remote" payload := alloc.NewSmallBuffer().Clear().Append([]byte(data2Send)) packet := v2net.NewPacket(v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), port), payload, false) err = freedom.Dispatch(packet, traffic) assert.Error(err).IsNil() close(traffic.InboundInput()) respPayload := <-traffic.InboundOutput() defer respPayload.Release() assert.Bytes(respPayload.Value).Equals([]byte("Processed: Data to be sent to remote")) _, open := <-traffic.InboundOutput() assert.Bool(open).IsFalse() tcpServer.Close() }
func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { vNextList := handler.vNextList if firstPacket.Destination().IsUDP() { vNextList = handler.vNextListUDP } vNextAddress, vNextUser := pickVNext(vNextList) command := protocol.CmdTCP if firstPacket.Destination().IsUDP() { command = protocol.CmdUDP } request := &protocol.VMessRequest{ Version: protocol.Version, User: vNextUser, Command: command, Address: firstPacket.Destination().Address(), } buffer := alloc.NewSmallBuffer() defer buffer.Release() v2net.ReadAllBytes(rand.Reader, buffer.Value[:36]) // 16 + 16 + 4 request.RequestIV = buffer.Value[:16] request.RequestKey = buffer.Value[16:32] request.ResponseHeader = buffer.Value[32:36] return startCommunicate(request, vNextAddress, ray, firstPacket) }
func TestSingleBytePayload(t *testing.T) { v2testing.Current(t) buffer := alloc.NewSmallBuffer().Clear().AppendBytes(1) _, err := ReadRequest(buffer, nil, false) assert.Error(err).Equals(transport.ErrorCorruptedPacket) }
func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { vNextAddress, vNextUser := this.receiverManager.PickReceiver() command := protocol.CmdTCP if firstPacket.Destination().IsUDP() { command = protocol.CmdUDP } request := &protocol.VMessRequest{ Version: protocol.Version, User: vNextUser, Command: command, Address: firstPacket.Destination().Address(), Port: firstPacket.Destination().Port(), } if command == protocol.CmdUDP { request.Option |= protocol.OptionChunk } buffer := alloc.NewSmallBuffer() defer buffer.Release() // Buffer is released after communication finishes. io.ReadFull(rand.Reader, buffer.Value[:33]) // 16 + 16 + 1 request.RequestIV = buffer.Value[:16] request.RequestKey = buffer.Value[16:32] request.ResponseHeader = buffer.Value[32] return this.startCommunicate(request, vNextAddress, ray, firstPacket) }
func TestEmptyPayload(t *testing.T) { assert := assert.On(t) buffer := alloc.NewSmallBuffer().Clear() _, err := ReadRequest(buffer, nil, false) assert.Error(err).Equals(io.EOF) }
func (this *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.ResponseHeader, error) { aesStream := crypto.NewAesDecryptionStream(this.responseBodyKey, this.responseBodyIV) this.responseReader = crypto.NewCryptionReader(aesStream, reader) buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err := io.ReadFull(this.responseReader, buffer.Value[:4]) if err != nil { log.Error("Raw: Failed to read response header: ", err) return nil, err } if buffer.Value[0] != this.responseHeader { log.Warning("Raw: Unexpected response header. Expecting %d, but actually %d", this.responseHeader, buffer.Value[0]) return nil, transport.ErrorCorruptedPacket } header := new(protocol.ResponseHeader) if buffer.Value[2] != 0 { cmdId := buffer.Value[2] dataLen := int(buffer.Value[3]) _, err := io.ReadFull(this.responseReader, buffer.Value[:dataLen]) if err != nil { log.Error("Raw: Failed to read response command: ", err) return nil, err } data := buffer.Value[:dataLen] command, err := UnmarshalCommand(cmdId, data) header.Command = command } return header, nil }
func (server *SocksServer) handleUDP(reader *v2net.TimeOutReader, writer io.Writer) error { response := protocol.NewSocks5Response() response.Error = protocol.ErrorSuccess udpAddr := server.getUDPAddr() response.Port = udpAddr.Port() switch { case udpAddr.IsIPv4(): response.SetIPv4(udpAddr.IP()) case udpAddr.IsIPv6(): response.SetIPv6(udpAddr.IP()) case udpAddr.IsDomain(): response.SetDomain(udpAddr.Domain()) } responseBuffer := alloc.NewSmallBuffer().Clear() response.Write(responseBuffer) _, err := writer.Write(responseBuffer.Value) responseBuffer.Release() if err != nil { log.Error("Socks failed to write response: %v", err) return err } reader.SetTimeOut(300) /* 5 minutes */ v2net.ReadFrom(reader, nil) // Just in case of anything left in the socket // The TCP connection closes after this method returns. We need to wait until // the client closes it. // TODO: get notified from UDP part <-time.After(5 * time.Minute) return nil }
func (this *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, payload *alloc.Buffer, input v2io.Reader, finish *sync.Mutex) { defer finish.Unlock() writer := v2io.NewBufferedWriter(conn) defer writer.Release() session.EncodeRequestHeader(request, writer) bodyWriter := session.EncodeRequestBody(writer) var streamWriter v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter) if request.Option.Has(protocol.RequestOptionChunkStream) { streamWriter = vmessio.NewAuthChunkWriter(streamWriter) } if err := streamWriter.Write(payload); err != nil { conn.SetReusable(false) } writer.SetCached(false) err := v2io.Pipe(input, streamWriter) if err != io.EOF { conn.SetReusable(false) } if request.Option.Has(protocol.RequestOptionChunkStream) { err := streamWriter.Write(alloc.NewSmallBuffer().Clear()) if err != nil { conn.SetReusable(false) } } streamWriter.Release() return }
func TestResponseWrite(t *testing.T) { assert := assert.On(t) response := Socks5Response{ socksVersion, ErrorSuccess, AddrTypeIPv4, [4]byte{0x72, 0x72, 0x72, 0x72}, "", [16]byte{}, v2net.Port(53), } buffer := alloc.NewSmallBuffer().Clear() defer buffer.Release() response.Write(buffer) expectedBytes := []byte{ socksVersion, ErrorSuccess, byte(0x00), AddrTypeIPv4, 0x72, 0x72, 0x72, 0x72, byte(0x00), byte(0x035), } assert.Bytes(buffer.Value).Equals(expectedBytes) }
func ReadUserPassRequest(reader io.Reader) (request Socks5UserPassRequest, err error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err = reader.Read(buffer.Value[0:2]) if err != nil { return } request.version = buffer.Value[0] nUsername := buffer.Value[1] nBytes, err := reader.Read(buffer.Value[:nUsername]) if err != nil { return } request.username = string(buffer.Value[:nBytes]) _, err = reader.Read(buffer.Value[0:1]) if err != nil { return } nPassword := buffer.Value[0] nBytes, err = reader.Read(buffer.Value[:nPassword]) if err != nil { return } request.password = string(buffer.Value[:nBytes]) return }
func (this *SocksServer) handlePacket(packet v2net.Packet, clientAddr *net.UDPAddr, targetAddr v2net.Address, port v2net.Port) { ray := this.space.PacketDispatcher().DispatchToOutbound(packet) close(ray.InboundInput()) for data := range ray.InboundOutput() { response := &protocol.Socks5UDPRequest{ Fragment: 0, Address: targetAddr, Port: port, Data: data, } log.Info("Socks: Writing back UDP response with ", data.Len(), " bytes from ", targetAddr, " to ", clientAddr) udpMessage := alloc.NewSmallBuffer().Clear() response.Write(udpMessage) this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() return } nBytes, err := this.udpConn.WriteToUDP(udpMessage.Value, clientAddr) this.udpMutex.RUnlock() udpMessage.Release() response.Data.Release() if err != nil { log.Error("Socks: failed to write UDP message (", nBytes, " bytes) to ", clientAddr, ": ", err) } } }
func TestRecivingQueue(t *testing.T) { assert := assert.On(t) queue := NewReceivingQueue(2) queue.Put(alloc.NewSmallBuffer().Clear().AppendString("abcd")) queue.Put(alloc.NewSmallBuffer().Clear().AppendString("efg")) assert.Bool(queue.IsFull()).IsTrue() b := make([]byte, 1024) nBytes := queue.Read(b) assert.Int(nBytes).Equals(7) assert.String(string(b[:nBytes])).Equals("abcdefg") queue.Put(alloc.NewSmallBuffer().Clear().AppendString("1")) queue.Close() nBytes = queue.Read(b) assert.Int(nBytes).Equals(0) }
func ReadRequest(reader io.Reader) (*Request, error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err := v2net.ReadAllBytes(reader, buffer.Value[:1]) if err != nil { log.Error("Shadowsocks: Failed to read address type: ", err) return nil, transport.CorruptedPacket } request := new(Request) addrType := buffer.Value[0] switch addrType { case AddrTypeIPv4: _, err := v2net.ReadAllBytes(reader, buffer.Value[:4]) if err != nil { log.Error("Shadowsocks: Failed to read IPv4 address: ", err) return nil, transport.CorruptedPacket } request.Address = v2net.IPAddress(buffer.Value[:4]) case AddrTypeIPv6: _, err := v2net.ReadAllBytes(reader, buffer.Value[:16]) if err != nil { log.Error("Shadowsocks: Failed to read IPv6 address: ", err) return nil, transport.CorruptedPacket } request.Address = v2net.IPAddress(buffer.Value[:16]) case AddrTypeDomain: _, err := v2net.ReadAllBytes(reader, buffer.Value[:1]) if err != nil { log.Error("Shadowsocks: Failed to read domain lenth: ", err) return nil, transport.CorruptedPacket } domainLength := int(buffer.Value[0]) _, err = v2net.ReadAllBytes(reader, buffer.Value[:domainLength]) if err != nil { log.Error("Shadowsocks: Failed to read domain: ", err) return nil, transport.CorruptedPacket } request.Address = v2net.DomainAddress(string(buffer.Value[:domainLength])) default: log.Error("Shadowsocks: Unknown address type: ", addrType) return nil, transport.CorruptedPacket } _, err = v2net.ReadAllBytes(reader, buffer.Value[:2]) if err != nil { log.Error("Shadowsocks: Failed to read port: ", err) return nil, transport.CorruptedPacket } request.Port = v2net.PortFromBytes(buffer.Value[:2]) return request, nil }
func TestSocks4AuthenticationResponseToBytes(t *testing.T) { assert := assert.On(t) response := NewSocks4AuthenticationResponse(byte(0x10), 443, []byte{1, 2, 3, 4}) buffer := alloc.NewSmallBuffer().Clear() defer buffer.Release() response.Write(buffer) assert.Bytes(buffer.Value).Equals([]byte{0x00, 0x10, 0x01, 0xBB, 0x01, 0x02, 0x03, 0x04}) }
// ToBytes returns a VMessRequest in the form of byte array. func (this *VMessRequest) ToBytes(timestampGenerator RandomTimestampGenerator, buffer *alloc.Buffer) (*alloc.Buffer, error) { if buffer == nil { buffer = alloc.NewSmallBuffer().Clear() } timestamp := timestampGenerator.Next() idHash := IDHash(this.User.AnyValidID().Bytes()) idHash.Write(timestamp.Bytes()) hashStart := buffer.Len() buffer.Slice(0, hashStart+16) idHash.Sum(buffer.Value[hashStart:hashStart]) encryptionBegin := buffer.Len() buffer.AppendBytes(this.Version) buffer.Append(this.RequestIV) buffer.Append(this.RequestKey) buffer.AppendBytes(this.ResponseHeader, this.Option, byte(0), byte(0)) buffer.AppendBytes(this.Command) buffer.Append(this.Port.Bytes()) switch { case this.Address.IsIPv4(): buffer.AppendBytes(addrTypeIPv4) buffer.Append(this.Address.IP()) case this.Address.IsIPv6(): buffer.AppendBytes(addrTypeIPv6) buffer.Append(this.Address.IP()) case this.Address.IsDomain(): buffer.AppendBytes(addrTypeDomain, byte(len(this.Address.Domain()))) buffer.Append([]byte(this.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 timestampHash := md5.New() timestampHash.Write(timestamp.HashBytes()) iv := timestampHash.Sum(nil) aesStream, err := v2crypto.NewAesEncryptionStream(this.User.ID.CmdKey(), iv) if err != nil { return nil, err } aesStream.XORKeyStream(buffer.Value[encryptionBegin:encryptionEnd], buffer.Value[encryptionBegin:encryptionEnd]) return buffer, nil }
func TestNormalRequestParsing(t *testing.T) { assert := assert.On(t) buffer := alloc.NewSmallBuffer().Clear() buffer.AppendBytes(1, 127, 0, 0, 1, 0, 80) request, err := ReadRequest(buffer, nil, false) assert.Error(err).IsNil() assert.Address(request.Address).Equals(v2net.LocalHostIP) assert.Port(request.Port).Equals(v2net.Port(80)) assert.Bool(request.OTA).IsFalse() }
func TestSetDomain(t *testing.T) { assert := assert.On(t) response := NewSocks5Response() response.SetDomain("v2ray.com") buffer := alloc.NewSmallBuffer().Clear() defer buffer.Release() response.Write(buffer) assert.Bytes(buffer.Value).Equals([]byte{ socksVersion, 0, 0, AddrTypeDomain, 9, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 0}) }
func TestNormalRequestParsing(t *testing.T) { v2testing.Current(t) buffer := alloc.NewSmallBuffer().Clear() buffer.AppendBytes(1, 127, 0, 0, 1, 0, 80) request, err := ReadRequest(buffer, nil, false) assert.Error(err).IsNil() netassert.Address(request.Address).Equals(v2net.IPAddress([]byte{127, 0, 0, 1})) netassert.Port(request.Port).Equals(v2net.Port(80)) assert.Bool(request.OTA).IsFalse() }
func TestSetIPv6(t *testing.T) { assert := assert.On(t) response := NewSocks5Response() response.SetIPv6([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) buffer := alloc.NewSmallBuffer().Clear() defer buffer.Release() response.Write(buffer) assert.Bytes(buffer.Value).Equals([]byte{ socksVersion, 0, 0, AddrTypeIPv6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0}) }
func TestInvalidOTARequest(t *testing.T) { v2testing.Current(t) buffer := alloc.NewSmallBuffer().Clear() buffer.AppendBytes(0x13, 13, 119, 119, 119, 46, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 0, 239, 115, 52, 212, 178, 172, 26, 6, 168, 1) auth := NewAuthenticator(HeaderKeyGenerator( []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5})) _, err := ReadRequest(buffer, auth, false) assert.Error(err).Equals(proxy.ErrorInvalidAuthentication) }
func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err = io.ReadFull(reader, buffer.Value[:4]) if err != nil { return } request = &Socks5Request{ Version: buffer.Value[0], Command: buffer.Value[1], // buffer[2] is a reserved field AddrType: buffer.Value[3], } switch request.AddrType { case AddrTypeIPv4: _, err = io.ReadFull(reader, request.IPv4[:]) if err != nil { return } case AddrTypeDomain: _, err = io.ReadFull(reader, buffer.Value[0:1]) if err != nil { return } domainLength := buffer.Value[0] _, err = io.ReadFull(reader, buffer.Value[:domainLength]) if err != nil { return } request.Domain = string(append([]byte(nil), buffer.Value[:domainLength]...)) case AddrTypeIPv6: _, err = io.ReadFull(reader, request.IPv6[:]) if err != nil { return } default: log.Warning("Socks: Unexpected address type ", request.AddrType) err = transport.ErrCorruptedPacket return } _, err = io.ReadFull(reader, buffer.Value[:2]) if err != nil { return } request.Port = v2net.PortFromBytes(buffer.Value[:2]) return }
func (this *HttpProxyServer) handlePlainHTTP(request *http.Request, dest v2net.Destination, reader *bufio.Reader, writer io.Writer) { if len(request.URL.Host) <= 0 { hdr := http.Header(make(map[string][]string)) hdr.Set("Connection", "close") response := &http.Response{ Status: "400 Bad Request", StatusCode: 400, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Header: hdr, Body: nil, ContentLength: 0, Close: false, } buffer := alloc.NewSmallBuffer().Clear() response.Write(buffer) writer.Write(buffer.Value) buffer.Release() return } request.Host = request.URL.Host stripHopByHopHeaders(request) requestBuffer := alloc.NewBuffer().Clear() request.Write(requestBuffer) log.Info("Request to remote:\n%s", string(requestBuffer.Value)) packet := v2net.NewPacket(dest, requestBuffer, true) ray := this.space.PacketDispatcher().DispatchToOutbound(packet) defer close(ray.InboundInput()) var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() responseReader := bufio.NewReader(NewChanReader(ray.InboundOutput())) responseBuffer := alloc.NewBuffer() defer responseBuffer.Release() response, err := http.ReadResponse(responseReader, request) if err != nil { return } responseBuffer.Clear() response.Write(responseBuffer) writer.Write(responseBuffer.Value) response.Body.Close() }() wg.Wait() }
func TestUDPRequestParsing(t *testing.T) { v2testing.Current(t) buffer := alloc.NewSmallBuffer().Clear() buffer.AppendBytes(1, 127, 0, 0, 1, 0, 80, 1, 2, 3, 4, 5, 6) request, err := ReadRequest(buffer, nil, true) assert.Error(err).IsNil() netassert.Address(request.Address).Equals(v2net.IPAddress([]byte{127, 0, 0, 1})) netassert.Port(request.Port).Equals(v2net.Port(80)) assert.Bool(request.OTA).IsFalse() assert.Bytes(request.UDPPayload.Value).Equals([]byte{1, 2, 3, 4, 5, 6}) }
func TestOTARequest(t *testing.T) { v2testing.Current(t) buffer := alloc.NewSmallBuffer().Clear() buffer.AppendBytes(0x13, 13, 119, 119, 119, 46, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 0, 239, 115, 52, 212, 178, 172, 26, 6, 168, 0) auth := NewAuthenticator(HeaderKeyGenerator( []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5})) request, err := ReadRequest(buffer, auth, false) assert.Error(err).IsNil() netassert.Address(request.Address).Equals(v2net.DomainAddress("www.v2ray.com")) assert.Bool(request.OTA).IsTrue() }
// 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 }
func (this *VMessOutboundHandler) handleResponse(conn net.Conn, request *protocol.VMessRequest, dest v2net.Destination, output chan<- *alloc.Buffer, finish *sync.Mutex) { defer finish.Unlock() defer close(output) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) aesStream, err := v2crypto.NewAesDecryptionStream(responseKey[:], responseIV[:]) if err != nil { log.Error("VMessOut: Failed to create AES encryption stream: ", err) return } decryptResponseReader := v2crypto.NewCryptionReader(aesStream, conn) buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err = io.ReadFull(decryptResponseReader, buffer.Value[:4]) if err != nil { log.Error("VMessOut: Failed to read VMess response (", buffer.Len(), " bytes): ", err) return } if !headerMatch(request, buffer.Value[0]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } if buffer.Value[2] != 0 { command := buffer.Value[2] dataLen := int(buffer.Value[3]) _, err := io.ReadFull(decryptResponseReader, buffer.Value[:dataLen]) if err != nil { log.Error("VMessOut: Failed to read response command: ", err) return } data := buffer.Value[:dataLen] go this.handleCommand(dest, command, data) } var reader v2io.Reader if request.IsChunkStream() { reader = vmessio.NewAuthChunkReader(decryptResponseReader) } else { reader = v2io.NewAdaptiveReader(decryptResponseReader) } v2io.ReaderToChan(output, reader) return }