func (this *SocksServer) handleUDP(reader *v2net.TimeOutReader, writer io.Writer) error { response := protocol.NewSocks5Response() response.Error = protocol.ErrorSuccess udpAddr := this.udpAddress response.Port = udpAddr.Port() switch { case udpAddr.Address().IsIPv4(): response.SetIPv4(udpAddr.Address().IP()) case udpAddr.Address().IsIPv6(): response.SetIPv6(udpAddr.Address().IP()) case udpAddr.Address().IsDomain(): response.SetDomain(udpAddr.Address().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: ", err) return err } reader.SetTimeOut(300) /* 5 minutes */ v2io.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 TestSocksTcpConnect(t *testing.T) { v2testing.Current(t) port := v2nettesting.PickPort() data2Send := "Data to be sent to remote" 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() pointPort := v2nettesting.PickPort() config := &point.Config{ Port: pointPort, InboundConfig: &point.ConnectionConfig{ Protocol: "socks", Settings: []byte(`{"auth": "noauth"}`), }, OutboundConfig: &point.ConnectionConfig{ Protocol: "freedom", Settings: nil, }, } point, err := point.NewPoint(config) assert.Error(err).IsNil() err = point.Start() assert.Error(err).IsNil() socks5Client, err := proxy.SOCKS5("tcp", fmt.Sprintf("127.0.0.1:%d", pointPort), nil, proxy.Direct) assert.Error(err).IsNil() targetServer := fmt.Sprintf("127.0.0.1:%d", port) conn, err := socks5Client.Dial("tcp", targetServer) assert.Error(err).IsNil() conn.Write([]byte(data2Send)) if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } dataReturned, err := v2io.ReadFrom(conn, nil) assert.Error(err).IsNil() conn.Close() assert.Bytes(dataReturned.Value).Equals([]byte("Processed: Data to be sent to remote")) }
func (server *Server) handleConnection(conn net.Conn) { for true { request, err := v2io.ReadFrom(conn, nil) if err != nil { break } response := server.MsgProcessor(request.Value) conn.Write(response) } conn.Close() }
func (this *VMessOutboundHandler) handleResponse(conn net.Conn, request *protocol.VMessRequest, dest v2net.Destination, output chan<- *alloc.Buffer, finish *sync.Mutex, isUDP bool) { 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, err := v2io.ReadFrom(decryptResponseReader, nil) if err != nil { log.Error("VMessOut: Failed to read VMess response (", buffer.Len(), " bytes): ", err) buffer.Release() return } if buffer.Len() < 4 || !headerMatch(request, buffer.Value[0]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } log.Info("VMessOut received ", buffer.Len()-4, " bytes from ", conn.RemoteAddr()) responseBegin := 4 if buffer.Value[2] != 0 { dataLen := int(buffer.Value[3]) if buffer.Len() < dataLen+4 { // Rare case diffBuffer := make([]byte, dataLen+4-buffer.Len()) io.ReadFull(decryptResponseReader, diffBuffer) buffer.Append(diffBuffer) } command := buffer.Value[2] data := buffer.Value[4 : 4+dataLen] go this.handleCommand(dest, command, data) responseBegin = 4 + dataLen } buffer.SliceFrom(responseBegin) output <- buffer if !isUDP { v2io.RawReaderToChan(output, decryptResponseReader) } return }
func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { log.Info("Freedom: Opening connection to ", firstPacket.Destination()) var conn net.Conn err := retry.Timed(5, 100).On(func() error { rawConn, err := dialer.Dial(firstPacket.Destination()) if err != nil { return err } conn = rawConn return nil }) if err != nil { close(ray.OutboundOutput()) log.Error("Freedom: Failed to open connection to ", firstPacket.Destination(), ": ", err) return err } defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() var readMutex, writeMutex sync.Mutex readMutex.Lock() writeMutex.Lock() if chunk := firstPacket.Chunk(); chunk != nil { conn.Write(chunk.Value) chunk.Release() } if !firstPacket.MoreChunks() { writeMutex.Unlock() } else { go func() { v2io.ChanToWriter(conn, input) writeMutex.Unlock() }() } go func() { defer readMutex.Unlock() defer close(output) response, err := v2io.ReadFrom(conn, nil) log.Info("Freedom receives ", response.Len(), " bytes from ", conn.RemoteAddr()) if response.Len() > 0 { output <- response } else { response.Release() } if err != nil { return } if firstPacket.Destination().IsUDP() { return } v2io.RawReaderToChan(output, conn) }() writeMutex.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } readMutex.Lock() return nil }