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 (this *DokodemoDoor) handleUDPPackets() { for this.accepting { buffer := alloc.NewBuffer() this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() return } nBytes, addr, err := this.udpConn.ReadFromUDP(buffer.Value) this.udpMutex.RUnlock() buffer.Slice(0, nBytes) if err != nil { buffer.Release() log.Error("Dokodemo failed to read from UDP: ", err) return } packet := v2net.NewPacket(v2net.UDPDestination(this.address, this.port), buffer, false) ray := this.space.PacketDispatcher().DispatchToOutbound(packet) close(ray.InboundInput()) for payload := range ray.InboundOutput() { this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() return } this.udpConn.WriteToUDP(payload.Value, addr) this.udpMutex.RUnlock() } } }
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 *VMessInboundHandler) AcceptPackets(conn *net.UDPConn) { for { buffer := make([]byte, bufferSize) nBytes, addr, err := conn.ReadFromUDP(buffer) if err != nil { log.Error("VMessIn failed to read UDP packets: %v", err) continue } reader := bytes.NewReader(buffer[:nBytes]) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(reader) if err != nil { log.Warning("VMessIn: Invalid request from (%s): %v", addr.String(), err) continue } cryptReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader) if err != nil { log.Error("VMessIn: Failed to create decrypt reader: %v", err) continue } data := make([]byte, bufferSize) nBytes, err = cryptReader.Read(data) if err != nil { log.Warning("VMessIn: Unable to decrypt data: %v", err) continue } packet := v2net.NewPacket(request.Destination(), data[:nBytes], false) go handler.handlePacket(conn, request, packet, addr) } }
func (server *SocksServer) AcceptPackets(conn *net.UDPConn) error { for { buffer := alloc.NewBuffer() nBytes, addr, err := conn.ReadFromUDP(buffer.Value) if err != nil { log.Error("Socks failed to read UDP packets: %v", err) buffer.Release() continue } log.Info("Client UDP connection from %v", addr) request, err := protocol.ReadUDPRequest(buffer.Value[:nBytes]) buffer.Release() if err != nil { log.Error("Socks failed to parse UDP request: %v", err) request.Data.Release() continue } if request.Fragment != 0 { log.Warning("Dropping fragmented UDP packets.") // TODO handle fragments request.Data.Release() continue } udpPacket := v2net.NewPacket(request.Destination(), request.Data, false) log.Info("Send packet to %s with %d bytes", udpPacket.Destination().String(), request.Data.Len()) go server.handlePacket(conn, udpPacket, addr, request.Address) } }
func (this *UDPServer) handleConnection(destString string, inboundRay ray.InboundRay, source v2net.Destination, callback UDPResponseCallback) { for buffer := range inboundRay.InboundOutput() { callback(v2net.NewPacket(source, buffer, false)) } this.Lock() delete(this.conns, destString) this.Unlock() }
func (this *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(16, connection) requestReader := protocol.NewVMessRequestReader(this.clients) request, err := requestReader.Read(connReader) if err != nil { log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, err.Error()) log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "") log.Debug("VMessIn: Received request for %s", request.Address.String()) ray := this.space.PacketDispatcher().DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() userSettings := vmess.GetUserSettings(request.User.Level) connReader.SetTimeOut(userSettings.PayloadReadTimeout) go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey) responseIV := md5.Sum(request.RequestIV) aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:]) if err != nil { log.Error("VMessIn: Failed to create AES decryption stream: %v", err) close(input) return err } responseWriter := v2crypto.NewCryptionWriter(aesStream, connection) // Optimize for small response packet buffer := alloc.NewLargeBuffer().Clear() defer buffer.Release() buffer.AppendBytes(request.ResponseHeader[0] ^ request.ResponseHeader[1]) buffer.AppendBytes(request.ResponseHeader[2] ^ request.ResponseHeader[3]) buffer.AppendBytes(byte(0), byte(0)) if data, open := <-output; open { buffer.Append(data.Value) data.Release() responseWriter.Write(buffer.Value) go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } connection.CloseWrite() readFinish.Lock() return nil }
func TestUDPSend(t *testing.T) { v2testing.Current(t) data2Send := "Data to be sent to remote" udpServer := &udp.Server{ Port: 0, MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } udpServerAddr, err := udpServer.Start() assert.Error(err).IsNil() connOutput := bytes.NewBuffer(make([]byte, 0, 1024)) ich := &proxymocks.InboundConnectionHandler{ ConnInput: bytes.NewReader([]byte("Not Used")), ConnOutput: connOutput, } protocol, err := proxytesting.RegisterInboundConnectionHandlerCreator("mock_ich", func(space app.Space, config interface{}) (v2proxy.InboundHandler, error) { ich.Space = space return ich, nil }) assert.Error(err).IsNil() pointPort := v2nettesting.PickPort() config := &point.Config{ Port: pointPort, InboundConfig: &point.ConnectionConfig{ Protocol: protocol, Settings: nil, }, OutboundConfig: &point.ConnectionConfig{ Protocol: "freedom", Settings: nil, }, } point, err := point.NewPoint(config) assert.Error(err).IsNil() err = point.Start() assert.Error(err).IsNil() data2SendBuffer := alloc.NewBuffer().Clear() data2SendBuffer.Append([]byte(data2Send)) ich.Communicate(v2net.NewPacket(udpServerAddr, data2SendBuffer, false)) assert.Bytes(connOutput.Bytes()).Equals([]byte("Processed: Data to be sent to remote")) }
func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(16, connection) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(connReader) if err != nil { log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, err.Error()) log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "") log.Debug("VMessIn: Received request for %s", request.Address.String()) ray := handler.dispatcher.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() connReader.SetTimeOut(120) go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey) responseIV := md5.Sum(request.RequestIV) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { log.Error("VMessIn: Failed to create encrypt writer: %v", err) return err } // Optimize for small response packet buffer := alloc.NewLargeBuffer().Clear() buffer.Append(request.ResponseHeader) if data, open := <-output; open { buffer.Append(data.Value) data.Release() responseWriter.Write(buffer.Value) buffer.Release() go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } connection.CloseWrite() readFinish.Lock() return nil }
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 (this *DokodemoDoor) handleUDPPackets(payload *alloc.Buffer, dest v2net.Destination) { packet := v2net.NewPacket(v2net.UDPDestination(this.address, this.port), payload, false) this.udpServer.Dispatch(dest, packet, func(packet v2net.Packet) { defer packet.Chunk().Release() this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() return } this.udpHub.WriteTo(packet.Chunk().Value, packet.Destination()) this.udpMutex.RUnlock() }) }
func TestUDPSend(t *testing.T) { assert := unit.Assert(t) data2Send := "Data to be sent to remote" udpServer := &udp.Server{ Port: 0, MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } udpServerAddr, err := udpServer.Start() assert.Error(err).IsNil() connOutput := bytes.NewBuffer(make([]byte, 0, 1024)) ich := &proxymocks.InboundConnectionHandler{ ConnInput: bytes.NewReader([]byte("Not Used")), ConnOutput: connOutput, } connhandler.RegisterInboundConnectionHandlerFactory("mock_ich", ich) pointPort := v2nettesting.PickPort() config := mocks.Config{ PortValue: pointPort, InboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "mock_ich", SettingsValue: nil, }, OutboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "freedom", SettingsValue: nil, }, } point, err := point.NewPoint(&config) assert.Error(err).IsNil() err = point.Start() assert.Error(err).IsNil() data2SendBuffer := alloc.NewBuffer().Clear() data2SendBuffer.Append([]byte(data2Send)) dest := v2net.NewUDPDestination(udpServerAddr) ich.Communicate(v2net.NewPacket(dest, data2SendBuffer, false)) assert.Bytes(connOutput.Bytes()).Equals([]byte("Processed: Data to be sent to remote")) }
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(4, connection) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(connReader) if err != nil { log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Debug("VMessIn: Received request for %s", request.Address.String()) ray := handler.vPoint.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) response := protocol.NewVMessResponse(request) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { return log.Error("VMessIn: Failed to create encrypt writer: %v", err) } // Optimize for small response packet buffer := make([]byte, 0, 2*1024) buffer = append(buffer, response[:]...) if data, open := <-output; open { buffer = append(buffer, data...) responseWriter.Write(buffer) go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } if tcpConn, ok := connection.(*net.TCPConn); ok { tcpConn.CloseWrite() } readFinish.Lock() return nil }
func TestUnreachableDestination(t *testing.T) { v2testing.Current(t) 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}), 128), payload, false) err := freedom.Dispatch(packet, traffic) assert.Error(err).IsNotNil() _, open := <-traffic.InboundOutput() assert.Bool(open).IsFalse() }
func (this *UDPServer) Dispatch(source v2net.Destination, packet v2net.Packet, callback UDPResponseCallback) { destString := source.String() + "-" + packet.Destination().String() if this.locateExistingAndDispatch(destString, packet) { return } this.Lock() inboundRay := this.packetDispatcher.DispatchToOutbound(v2net.NewPacket(packet.Destination(), packet.Chunk(), true)) this.conns[destString] = &connEntry{ inboundRay: inboundRay, callback: callback, } this.Unlock() go this.handleConnection(destString, inboundRay, source, callback) }
func TestUDPSend(t *testing.T) { assert := unit.Assert(t) data2Send := "Data to be sent to remote" udpServer := &udp.Server{ Port: 0, MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } udpServerAddr, err := udpServer.Start() assert.Error(err).IsNil() ich := &mocks.InboundConnectionHandler{ Data2Send: []byte("Not Used"), DataReturned: bytes.NewBuffer(make([]byte, 0, 1024)), } core.RegisterInboundConnectionHandlerFactory("mock_ich", ich) pointPort := uint16(38724) config := mocks.Config{ PortValue: pointPort, InboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "mock_ich", ContentValue: nil, }, OutboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "freedom", ContentValue: nil, }, } point, err := core.NewPoint(&config) assert.Error(err).IsNil() err = point.Start() assert.Error(err).IsNil() dest := v2net.NewUDPDestination(udpServerAddr) ich.Communicate(v2net.NewPacket(dest, []byte(data2Send), false)) assert.Bytes(ich.DataReturned.Bytes()).Equals([]byte("Processed: Data to be sent to remote")) }
func (this *SocksServer) handleUDPPayload(payload *alloc.Buffer, source v2net.Destination) { log.Info("Socks: Client UDP connection from ", source) request, err := protocol.ReadUDPRequest(payload.Value) payload.Release() if err != nil { log.Error("Socks: Failed to parse UDP request: ", err) return } if request.Data.Len() == 0 { request.Data.Release() return } if request.Fragment != 0 { log.Warning("Socks: Dropping fragmented UDP packets.") // TODO handle fragments request.Data.Release() return } udpPacket := v2net.NewPacket(request.Destination(), request.Data, false) log.Info("Socks: Send packet to ", udpPacket.Destination(), " with ", request.Data.Len(), " bytes") this.udpServer.Dispatch(source, udpPacket, func(packet v2net.Packet) { response := &protocol.Socks5UDPRequest{ Fragment: 0, Address: udpPacket.Destination().Address(), Port: udpPacket.Destination().Port(), Data: packet.Chunk(), } log.Info("Socks: Writing back UDP response with ", response.Data.Len(), " bytes to ", packet.Destination()) udpMessage := alloc.NewSmallBuffer().Clear() response.Write(udpMessage) this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() return } nBytes, err := this.udpHub.WriteTo(udpMessage.Value, packet.Destination()) this.udpMutex.RUnlock() udpMessage.Release() response.Data.Release() if err != nil { log.Error("Socks: failed to write UDP message (", nBytes, " bytes) to ", packet.Destination(), ": ", err) } }) }
func (this *DokodemoDoor) HandleTCPConnection(conn *hub.TCPConn) { defer conn.Close() packet := v2net.NewPacket(v2net.TCPDestination(this.address, this.port), nil, true) ray := this.packetDispatcher.DispatchToOutbound(packet) var inputFinish, outputFinish sync.Mutex inputFinish.Lock() outputFinish.Lock() reader := v2net.NewTimeOutReader(this.config.Timeout, conn) go dumpInput(reader, ray.InboundInput(), &inputFinish) go dumpOutput(conn, ray.InboundOutput(), &outputFinish) outputFinish.Lock() }
func (this *DokodemoDoor) handleUDPPackets(payload *alloc.Buffer, dest v2net.Destination) { packet := v2net.NewPacket(v2net.UDPDestination(this.address, this.port), payload, false) ray := this.packetDispatcher.DispatchToOutbound(packet) close(ray.InboundInput()) for resp := range ray.InboundOutput() { this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() resp.Release() return } this.udpHub.WriteTo(resp.Value, dest) this.udpMutex.RUnlock() resp.Release() } }
func (handler *VMessInboundHandler) AcceptPackets(conn *net.UDPConn) { for { buffer := alloc.NewBuffer() nBytes, addr, err := conn.ReadFromUDP(buffer.Value) if err != nil { log.Error("VMessIn failed to read UDP packets: %v", err) buffer.Release() continue } reader := bytes.NewReader(buffer.Value[:nBytes]) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(reader) if err != nil { log.Access(addr.String(), "", log.AccessRejected, err.Error()) log.Warning("VMessIn: Invalid request from (%s): %v", addr.String(), err) buffer.Release() continue } log.Access(addr.String(), request.Address.String(), log.AccessAccepted, "") cryptReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader) if err != nil { log.Error("VMessIn: Failed to create decrypt reader: %v", err) buffer.Release() continue } data := alloc.NewBuffer() nBytes, err = cryptReader.Read(data.Value) buffer.Release() if err != nil { log.Warning("VMessIn: Unable to decrypt data: %v", err) data.Release() continue } data.Slice(0, nBytes) packet := v2net.NewPacket(request.Destination(), data, false) go handler.handlePacket(conn, request, packet, addr) } }
func (this *Point) FilterPacketAndDispatch(packet v2net.Packet, link ray.OutboundRay, dispatcher proxy.OutboundConnectionHandler) { // Filter empty packets chunk := packet.Chunk() moreChunks := packet.MoreChunks() changed := false for chunk == nil && moreChunks { changed = true chunk, moreChunks = <-link.OutboundInput() } if chunk == nil && !moreChunks { close(link.OutboundOutput()) return } if changed { packet = v2net.NewPacket(packet.Destination(), chunk, moreChunks) } dispatcher.Dispatch(packet, link) }
func (this *DokodemoDoor) handleUDPPackets(udpConn *net.UDPConn) { defer udpConn.Close() for this.accepting { buffer := alloc.NewBuffer() nBytes, addr, err := udpConn.ReadFromUDP(buffer.Value) buffer.Slice(0, nBytes) if err != nil { buffer.Release() log.Error("Dokodemo failed to read from UDP: %v", err) return } packet := v2net.NewPacket(v2net.NewUDPDestination(this.address), buffer, false) ray := this.dispatcher.DispatchToOutbound(packet) close(ray.InboundInput()) for payload := range ray.InboundOutput() { udpConn.WriteToUDP(payload.Value, addr) } } }
func (this *HttpProxyServer) handleConnect(request *http.Request, destination v2net.Destination, reader io.Reader, writer io.Writer) { response := &http.Response{ Status: "200 OK", StatusCode: 200, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Header: http.Header(make(map[string][]string)), Body: nil, ContentLength: 0, Close: false, } buffer := alloc.NewSmallBuffer().Clear() response.Write(buffer) writer.Write(buffer.Value) buffer.Release() packet := v2net.NewPacket(destination, nil, true) ray := this.packetDispatcher.DispatchToOutbound(packet) this.transport(reader, writer, ray) }
func (server *SocksServer) AcceptPackets(conn *net.UDPConn) error { for { buffer := make([]byte, bufferSize) nBytes, addr, err := conn.ReadFromUDP(buffer) if err != nil { log.Error("Socks failed to read UDP packets: %v", err) return err } request, err := protocol.ReadUDPRequest(buffer[:nBytes]) if err != nil { log.Error("Socks failed to parse UDP request: %v", err) return err } if request.Fragment != 0 { // TODO handle fragments continue } udpPacket := v2net.NewPacket(request.Destination(), request.Data, false) go server.handlePacket(conn, udpPacket, addr) } }
func (this *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("Socks: Unsupported socks 4 command ", auth.Command) return ErrorUnsupportedSocksCommand } dest := v2net.TCPDestination(v2net.IPAddress(auth.IP[:]), auth.Port) packet := v2net.NewPacket(dest, nil, true) this.transport(reader, writer, packet) return nil }
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[:]) writer.Write(socks4Response.ToBytes(nil)) if result == protocol.Socks4RequestRejected { return errors.NewInvalidOperationError("Socks4 command " + strconv.Itoa(int(auth.Command))) } dest := v2net.NewTCPDestination(v2net.IPAddress(auth.IP[:], auth.Port)) data, err := v2net.ReadFrom(reader) if err != nil { return err } packet := v2net.NewPacket(dest, data, true) server.transport(reader, writer, packet) return nil }
func (this *SocksServer) handleSocks4(reader *v2io.BufferedReader, writer *v2io.BufferedWriter, auth protocol.Socks4AuthenticationRequest) error { result := protocol.Socks4RequestGranted if auth.Command == protocol.CmdBind { result = protocol.Socks4RequestRejected } socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth.Port, auth.IP[:]) socks4Response.Write(writer) if result == protocol.Socks4RequestRejected { log.Warning("Socks: Unsupported socks 4 command ", auth.Command) return ErrorUnsupportedSocksCommand } reader.SetCached(false) writer.SetCached(false) dest := v2net.TCPDestination(v2net.IPAddress(auth.IP[:]), auth.Port) packet := v2net.NewPacket(dest, nil, true) this.transport(reader, writer, packet) return nil }
func (this *SocksServer) AcceptPackets() error { for this.accepting { buffer := alloc.NewBuffer() this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() return nil } nBytes, addr, err := this.udpConn.ReadFromUDP(buffer.Value) this.udpMutex.RUnlock() if err != nil { log.Error("Socks: failed to read UDP packets: ", err) buffer.Release() continue } log.Info("Socks: Client UDP connection from ", addr) request, err := protocol.ReadUDPRequest(buffer.Value[:nBytes]) buffer.Release() if err != nil { log.Error("Socks: failed to parse UDP request: ", err) continue } if request.Data == nil || request.Data.Len() == 0 { continue } if request.Fragment != 0 { log.Warning("Socks: Dropping fragmented UDP packets.") // TODO handle fragments request.Data.Release() continue } udpPacket := v2net.NewPacket(request.Destination(), request.Data, false) log.Info("Socks: Send packet to ", udpPacket.Destination(), " with ", request.Data.Len(), " bytes") go this.handlePacket(udpPacket, addr, request.Address, request.Port) } return nil }
func (server *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.Writer, auth protocol.Socks5AuthenticationRequest) error { expectedAuthMethod := protocol.AuthNotRequired if server.config.IsPassword() { expectedAuthMethod = protocol.AuthUserPass } if !auth.HasAuthMethod(expectedAuthMethod) { authResponse := protocol.NewAuthenticationResponse(protocol.AuthNoMatchingMethod) err := protocol.WriteAuthentication(writer, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } log.Warning("Socks client doesn't support allowed any auth methods.") return UnsupportedAuthMethod } authResponse := protocol.NewAuthenticationResponse(expectedAuthMethod) err := protocol.WriteAuthentication(writer, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } if server.config.IsPassword() { upRequest, err := protocol.ReadUserPassRequest(reader) if err != nil { log.Error("Socks failed to read username and password: %v", err) return err } status := byte(0) if !server.config.HasAccount(upRequest.Username(), upRequest.Password()) { status = byte(0xFF) } upResponse := protocol.NewSocks5UserPassResponse(status) err = protocol.WriteUserPassResponse(writer, upResponse) if err != nil { log.Error("Socks failed to write user pass response: %v", err) return err } if status != byte(0) { log.Warning("Invalid user account: %s", upRequest.AuthDetail()) return proxyerrors.InvalidAuthentication } } request, err := protocol.ReadRequest(reader) if err != nil { log.Error("Socks failed to read request: %v", err) return err } if request.Command == protocol.CmdUdpAssociate && server.config.UDPEnabled { return server.handleUDP(reader, writer) } if request.Command == protocol.CmdBind || request.Command == protocol.CmdUdpAssociate { response := protocol.NewSocks5Response() response.Error = protocol.ErrorCommandNotSupported 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 } log.Warning("Unsupported socks command %d", request.Command) return UnsupportedSocksCommand } response := protocol.NewSocks5Response() response.Error = protocol.ErrorSuccess // Some SOCKS software requires a value other than dest. Let's fake one: response.Port = uint16(1717) response.AddrType = protocol.AddrTypeIPv4 response.IPv4[0] = 0 response.IPv4[1] = 0 response.IPv4[2] = 0 response.IPv4[3] = 0 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 } dest := request.Destination() 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 TestVMessInAndOut(t *testing.T) { v2testing.Current(t) id, err := uuid.ParseString("ad937d9d-6e23-4a5a-ba23-bce5092a7c51") assert.Error(err).IsNil() testAccount := vmess.NewID(id) portA := v2nettesting.PickPort() portB := v2nettesting.PickPort() ichConnInput := []byte("The data to be send to outbound server.") ichConnOutput := bytes.NewBuffer(make([]byte, 0, 1024)) ich := &proxymocks.InboundConnectionHandler{ ConnInput: bytes.NewReader(ichConnInput), ConnOutput: ichConnOutput, } protocol, err := proxytesting.RegisterInboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (proxy.InboundHandler, error) { ich.Space = space return ich, nil }) assert.Error(err).IsNil() configA := &point.Config{ Port: portA, InboundConfig: &point.ConnectionConfig{ Protocol: protocol, Settings: nil, }, OutboundConfig: &point.ConnectionConfig{ Protocol: "vmess", Settings: []byte(`{ "vnext": [ { "address": "127.0.0.1", "port": ` + portB.String() + `, "users": [ {"id": "` + testAccount.String() + `"} ] } ] }`), }, } pointA, err := point.NewPoint(configA) assert.Error(err).IsNil() err = pointA.Start() assert.Error(err).IsNil() ochConnInput := []byte("The data to be returned to inbound server.") ochConnOutput := bytes.NewBuffer(make([]byte, 0, 1024)) och := &proxymocks.OutboundConnectionHandler{ ConnInput: bytes.NewReader(ochConnInput), ConnOutput: ochConnOutput, } protocol, err = proxytesting.RegisterOutboundConnectionHandlerCreator("mock_och", func(space app.Space, config interface{}) (proxy.OutboundHandler, error) { return och, nil }) assert.Error(err).IsNil() configB := &point.Config{ Port: portB, InboundConfig: &point.ConnectionConfig{ Protocol: "vmess", Settings: []byte(`{ "clients": [ {"id": "` + testAccount.String() + `"} ] }`), }, OutboundConfig: &point.ConnectionConfig{ Protocol: protocol, Settings: nil, }, } pointB, err := point.NewPoint(configB) assert.Error(err).IsNil() err = pointB.Start() assert.Error(err).IsNil() dest := v2net.TCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80) ich.Communicate(v2net.NewPacket(dest, nil, true)) assert.Bytes(ichConnInput).Equals(ochConnOutput.Bytes()) assert.Bytes(ichConnOutput.Bytes()).Equals(ochConnInput) }