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 *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { conn, err := net.Dial(firstPacket.Destination().Network(), firstPacket.Destination().Address().String()) log.Info("Freedom: Opening connection to %s", firstPacket.Destination().String()) if err != nil { close(ray.OutboundOutput()) log.Error("Freedom: Failed to open connection: %s : %v", firstPacket.Destination().String(), err) return err } 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() { v2net.ChanToWriter(conn, input) writeMutex.Unlock() }() } go func() { defer readMutex.Unlock() defer close(output) response, err := v2net.ReadFrom(conn, nil) log.Info("Freedom receives %d bytes from %s", response.Len(), conn.RemoteAddr().String()) if response.Len() > 0 { output <- response } else { response.Release() } if err != nil { return } if firstPacket.Destination().IsUDP() { return } v2net.ReaderToChan(output, conn) }() writeMutex.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } readMutex.Lock() conn.Close() return nil }
func (this *DokodemoDoor) HandleTCPConnection(conn internet.Connection) { defer conn.Close() var dest v2net.Destination if this.config.FollowRedirect { originalDest := GetOriginalDestination(conn) if originalDest != nil { log.Info("Dokodemo: Following redirect to: ", originalDest) dest = originalDest } } if dest == nil && this.address != nil && this.port > v2net.Port(0) { dest = v2net.TCPDestination(this.address, this.port) } if dest == nil { log.Info("Dokodemo: Unknown destination, stop forwarding...") return } log.Info("Dokodemo: Handling request to ", dest) ray := this.packetDispatcher.DispatchToOutbound(dest) defer ray.InboundOutput().Release() var inputFinish, outputFinish sync.Mutex inputFinish.Lock() outputFinish.Lock() reader := v2net.NewTimeOutReader(this.config.Timeout, conn) defer reader.Release() go func() { v2reader := v2io.NewAdaptiveReader(reader) defer v2reader.Release() v2io.Pipe(v2reader, ray.InboundInput()) inputFinish.Unlock() ray.InboundInput().Close() }() go func() { v2writer := v2io.NewAdaptiveWriter(conn) defer v2writer.Release() v2io.Pipe(ray.InboundOutput(), v2writer) outputFinish.Unlock() }() outputFinish.Lock() inputFinish.Lock() }
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) } }) }
// Close closes the connection. func (this *Connection) Close() error { if this == nil { return errClosedConnection } this.dataInputCond.Broadcast() this.dataOutputCond.Broadcast() state := this.State() if state == StateReadyToClose || state == StateTerminating || state == StateTerminated { return errClosedConnection } log.Info("KCP|Connection: Closing connection to ", this.remote) if state == StateActive { this.SetState(StateReadyToClose) } if state == StatePeerClosed { this.SetState(StateTerminating) } if state == StatePeerTerminating { this.SetState(StateTerminated) } return nil }
// NewConnection create a new KCP connection between local and remote. func NewConnection(conv uint16, writerCloser io.WriteCloser, local *net.UDPAddr, remote *net.UDPAddr, block Authenticator) *Connection { log.Info("KCP|Connection: creating connection ", conv) conn := new(Connection) conn.local = local conn.remote = remote conn.block = block conn.writer = writerCloser conn.since = nowMillisec() conn.dataInputCond = sync.NewCond(new(sync.Mutex)) conn.dataOutputCond = sync.NewCond(new(sync.Mutex)) authWriter := &AuthenticationWriter{ Authenticator: block, Writer: writerCloser, } conn.conv = conv conn.output = NewSegmentWriter(authWriter) conn.mss = authWriter.Mtu() - DataSegmentOverhead conn.roundTrip = &RountTripInfo{ rto: 100, minRtt: effectiveConfig.Tti, } conn.interval = effectiveConfig.Tti conn.receivingWorker = NewReceivingWorker(conn) conn.fastresend = 2 conn.congestionControl = effectiveConfig.Congestion conn.sendingWorker = NewSendingWorker(conn) go conn.updateTask() return conn }
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.ChanToRawWriter(conn, input) writeMutex.Unlock() }() } go func() { defer readMutex.Unlock() defer close(output) var reader io.Reader = conn if firstPacket.Destination().IsUDP() { reader = v2net.NewTimeOutReader(16 /* seconds */, conn) } v2io.RawReaderToChan(output, reader) }() writeMutex.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } readMutex.Lock() return nil }
func (handler *VMessInboundHandler) handlePacket(conn *net.UDPConn, request *protocol.VMessRequest, packet v2net.Packet, clientAddr *net.UDPAddr) { ray := handler.vPoint.DispatchToOutbound(packet) close(ray.InboundInput()) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) buffer := bytes.NewBuffer(make([]byte, 0, bufferSize)) response := protocol.NewVMessResponse(request) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], buffer) if err != nil { log.Error("VMessIn: Failed to create encrypt writer: %v", err) return } responseWriter.Write(response[:]) hasData := false if data, ok := <-ray.InboundOutput(); ok { hasData = true responseWriter.Write(data) } if hasData { conn.WriteToUDP(buffer.Bytes(), clientAddr) log.Info("VMessIn sending %d bytes to %s", len(buffer.Bytes()), clientAddr.String()) } }
func (this *VMessInboundHandler) generateCommand(request *protocol.RequestHeader) protocol.ResponseCommand { if this.detours != nil { tag := this.detours.ToTag if this.inboundHandlerManager != nil { handler, availableMin := this.inboundHandlerManager.GetHandler(tag) inboundHandler, ok := handler.(*VMessInboundHandler) if ok { if availableMin > 255 { availableMin = 255 } log.Info("VMessIn: Pick detour handler for port ", inboundHandler.Port(), " for ", availableMin, " minutes.") user := inboundHandler.GetUser(request.User.Email) if user == nil { return nil } return &protocol.CommandSwitchAccount{ Port: inboundHandler.Port(), ID: user.Account.(*vmess.Account).ID.UUID(), AlterIds: uint16(len(user.Account.(*vmess.Account).AlterIDs)), Level: user.Level, ValidMin: byte(availableMin), } } } } return nil }
func (vconn *FreedomConnection) Start(ray core.OutboundRay) error { conn, err := net.Dial(vconn.packet.Destination().Network(), vconn.packet.Destination().Address().String()) log.Info("Freedom: Opening connection to %s", vconn.packet.Destination().String()) if err != nil { if ray != nil { close(ray.OutboundOutput()) } return log.Error("Freedom: Failed to open connection: %s : %v", vconn.packet.Destination().String(), err) } if chunk := vconn.packet.Chunk(); chunk != nil { conn.Write(chunk) } if !vconn.packet.MoreChunks() { if ray != nil { close(ray.OutboundOutput()) } return nil } input := ray.OutboundInput() output := ray.OutboundOutput() readFinish := make(chan bool) writeFinish := make(chan bool) go dumpInput(conn, input, writeFinish) go dumpOutput(conn, output, readFinish) go closeConn(conn, readFinish, writeFinish) return nil }
func (this *HttpProxyServer) handleConnection(conn *hub.TCPConn) { defer conn.Close() reader := bufio.NewReader(conn) request, err := http.ReadRequest(reader) if err != nil { log.Warning("Failed to read http request: ", err) return } log.Info("Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("Malformed proxy host (", host, "): ", err) return } if strings.ToUpper(request.Method) == "CONNECT" { this.handleConnect(request, dest, reader, conn) } else { this.handlePlainHTTP(request, dest, reader, conn) } }
func (handler *VMessInboundHandler) handlePacket(conn *net.UDPConn, request *protocol.VMessRequest, packet v2net.Packet, clientAddr *net.UDPAddr) { ray := handler.vPoint.DispatchToOutbound(packet) close(ray.InboundInput()) responseKey := md5.Sum(request.RequestKey) responseIV := md5.Sum(request.RequestIV) buffer := alloc.NewBuffer().Clear() defer buffer.Release() responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], buffer) if err != nil { log.Error("VMessIn: Failed to create encrypt writer: %v", err) return } responseWriter.Write(request.ResponseHeader) hasData := false if data, ok := <-ray.InboundOutput(); ok { hasData = true responseWriter.Write(data.Value) data.Release() } if hasData { conn.WriteToUDP(buffer.Value, clientAddr) log.Info("VMessIn sending %d bytes to %s", buffer.Len(), clientAddr.String()) } }
func startCommunicate(request *protocol.VMessRequest, dest *v2net.Destination, ray core.OutboundRay) error { input := ray.OutboundInput() output := ray.OutboundOutput() conn, err := net.DialTCP(dest.Network(), nil, &net.TCPAddr{dest.Address().IP(), int(dest.Address().Port()), ""}) if err != nil { log.Error("Failed to open tcp (%s): %v", dest.String(), err) close(output) return err } log.Info("VMessOut: Tunneling request for %s", request.Address.String()) defer conn.Close() requestFinish := make(chan bool) responseFinish := make(chan bool) go handleRequest(conn, request, input, requestFinish) go handleResponse(conn, request, output, responseFinish) <-requestFinish conn.CloseWrite() <-responseFinish return nil }
func (this *Server) handleConnection(conn internet.Connection) { defer conn.Close() timedReader := v2net.NewTimeOutReader(this.config.Timeout, conn) reader := bufio.NewReaderSize(timedReader, 2048) request, err := http.ReadRequest(reader) if err != nil { if err != io.EOF { log.Warning("HTTP: Failed to read http request: ", err) } return } log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("HTTP: Malformed proxy host (", host, "): ", err) return } log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "") if strings.ToUpper(request.Method) == "CONNECT" { this.handleConnect(request, dest, reader, conn) } else { this.handlePlainHTTP(request, dest, reader, conn) } }
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 handleResponse(conn net.Conn, request *protocol.VMessRequest, 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[:]) decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn) if err != nil { log.Error("VMessOut: Failed to create decrypt reader: %v", err) return } buffer, err := v2net.ReadFrom(decryptResponseReader, nil) if err != nil { log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", buffer.Len(), err) return } if buffer.Len() < 4 || !bytes.Equal(buffer.Value[:4], request.ResponseHeader[:]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } log.Info("VMessOut received %d bytes from %s", buffer.Len()-4, conn.RemoteAddr().String()) buffer.SliceFrom(4) output <- buffer if !isUDP { v2net.ReaderToChan(output, decryptResponseReader) } return }
func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ray core.OutboundRay, firstPacket v2net.Packet) error { conn, err := net.Dial(dest.Network(), dest.Address().String()) if err != nil { log.Error("Failed to open %s: %v", dest.String(), err) if ray != nil { close(ray.OutboundOutput()) } return err } log.Info("VMessOut: Tunneling request to %s via %s", request.Address.String(), dest.String()) defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() var requestFinish, responseFinish sync.Mutex requestFinish.Lock() responseFinish.Lock() go handleRequest(conn, request, firstPacket, input, &requestFinish) go handleResponse(conn, request, output, &responseFinish, dest.IsUDP()) requestFinish.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } responseFinish.Lock() return nil }
func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error { defer ray.OutboundInput().Release() defer ray.OutboundOutput().Close() var rec *protocol.ServerSpec var conn internet.Connection err := retry.Timed(5, 100).On(func() error { rec = this.serverPicker.PickServer() rawConn, err := internet.Dial(this.meta.Address, rec.Destination(), this.meta.StreamSettings) if err != nil { return err } conn = rawConn return nil }) if err != nil { log.Error("VMess|Outbound: Failed to find an available destination:", err) return err } log.Info("VMess|Outbound: Tunneling request to ", target, " via ", rec.Destination) command := protocol.RequestCommandTCP if target.IsUDP() { command = protocol.RequestCommandUDP } request := &protocol.RequestHeader{ Version: encoding.Version, User: rec.PickUser(), Command: command, Address: target.Address(), Port: target.Port(), Option: protocol.RequestOptionChunkStream, } defer conn.Close() conn.SetReusable(true) if conn.Reusable() { // Conn reuse may be disabled on transportation layer request.Option.Set(protocol.RequestOptionConnectionReuse) } input := ray.OutboundInput() output := ray.OutboundOutput() var requestFinish, responseFinish sync.Mutex requestFinish.Lock() responseFinish.Lock() session := encoding.NewClientSession(protocol.DefaultIDHash) go this.handleRequest(session, conn, request, payload, input, &requestFinish) go this.handleResponse(session, conn, request, rec.Destination(), output, &responseFinish) requestFinish.Lock() responseFinish.Lock() return nil }
func (this *Connection) Terminate() { if this == nil || this.writer == nil { return } log.Info("KCP|Connection: Terminating connection to ", this.RemoteAddr()) this.writer.Close() }
func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, auth4 Socks4AuthenticationRequest, err error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() nBytes, err := reader.Read(buffer.Value) if err != nil { return } if nBytes < 2 { log.Info("Socks expected 2 bytes read, but only %d bytes read", nBytes) err = transport.CorruptedPacket return } if buffer.Value[0] == socks4Version { auth4.Version = buffer.Value[0] auth4.Command = buffer.Value[1] auth4.Port = binary.BigEndian.Uint16(buffer.Value[2:4]) copy(auth4.IP[:], buffer.Value[4:8]) err = Socks4Downgrade return } auth.version = buffer.Value[0] if auth.version != socksVersion { log.Warning("Unknown protocol version %d", auth.version) err = proxy.InvalidProtocolVersion return } auth.nMethods = buffer.Value[1] if auth.nMethods <= 0 { log.Info("Zero length of authentication methods") err = transport.CorruptedPacket return } if nBytes-2 != int(auth.nMethods) { log.Info("Unmatching number of auth methods, expecting %d, but got %d", auth.nMethods, nBytes) err = transport.CorruptedPacket return } copy(auth.authMethods[:], buffer.Value[2:nBytes]) return }
// @Private func (this *DefaultDispatcher) FilterPacketAndDispatch(destination v2net.Destination, link ray.OutboundRay, dispatcher proxy.OutboundHandler) { payload, err := link.OutboundInput().Read() if err != nil { log.Info("DefaultDispatcher: No payload towards ", destination, ", stopping now.") link.OutboundInput().Release() link.OutboundOutput().Release() return } dispatcher.Dispatch(destination, payload, link) }
func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, auth4 Socks4AuthenticationRequest, err error) { buffer := make([]byte, 256) nBytes, err := reader.Read(buffer) if err != nil { return } if nBytes < 2 { log.Info("Socks expected 2 bytes read, but only %d bytes read", nBytes) err = errors.NewCorruptedPacketError() return } if buffer[0] == socks4Version { auth4.Version = buffer[0] auth4.Command = buffer[1] auth4.Port = binary.BigEndian.Uint16(buffer[2:4]) copy(auth4.IP[:], buffer[4:8]) err = NewSocksVersion4Error() return } auth.version = buffer[0] if auth.version != socksVersion { err = errors.NewProtocolVersionError(int(auth.version)) return } auth.nMethods = buffer[1] if auth.nMethods <= 0 { log.Info("Zero length of authentication methods") err = errors.NewCorruptedPacketError() return } if nBytes-2 != int(auth.nMethods) { log.Info("Unmatching number of auth methods, expecting %d, but got %d", auth.nMethods, nBytes) err = errors.NewCorruptedPacketError() return } copy(auth.authMethods[:], buffer[2:nBytes]) return }
func (this *DefaultDispatcher) DispatchToOutbound(destination v2net.Destination) ray.InboundRay { direct := ray.NewRay() dispatcher := this.ohm.GetDefaultHandler() if this.router != nil { if tag, err := this.router.TakeDetour(destination); err == nil { if handler := this.ohm.GetHandler(tag); handler != nil { log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].") dispatcher = handler } else { log.Warning("DefaultDispatcher: Nonexisting tag: ", tag) } } else { log.Info("DefaultDispatcher: Default route for ", destination) } } go this.FilterPacketAndDispatch(destination, direct, dispatcher) return direct }
// @Private func (this *FreedomConnection) ResolveIP(destination v2net.Destination) v2net.Destination { if !destination.Address().IsDomain() { return destination } ips := this.dns.Get(destination.Address().Domain()) if len(ips) == 0 { log.Info("Freedom: DNS returns nil answer. Keep domain as is.") return destination } ip := ips[dice.Roll(len(ips))] var newDest v2net.Destination if destination.IsTCP() { newDest = v2net.TCPDestination(v2net.IPAddress(ip), destination.Port()) } else { newDest = v2net.UDPDestination(v2net.IPAddress(ip), destination.Port()) } log.Info("Freedom: Changing destination from ", destination, " to ", newDest) return newDest }
func GetOriginalDestination(conn internet.Connection) v2net.Destination { tcpConn, ok := conn.(internet.SysFd) if !ok { log.Info("Dokodemo: Failed to get sys fd.") return nil } fd, err := tcpConn.SysFd() if err != nil { log.Info("Dokodemo: Failed to get original destination: ", err) return nil } addr, err := syscall.GetsockoptIPv6Mreq(fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST) if err != nil { log.Info("Dokodemo: Failed to call getsockopt: ", err) return nil } ip := v2net.IPAddress(addr.Multiaddr[4:8]) port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) return v2net.TCPDestination(ip, v2net.Port(port)) }
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 *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 (this *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.ResponseHeader, error) { aesStream := crypto.NewAesDecryptionStream(this.responseBodyKey, this.responseBodyIV) this.responseReader = crypto.NewCryptionReader(aesStream, reader) buffer := make([]byte, 256) _, err := io.ReadFull(this.responseReader, buffer[:4]) if err != nil { log.Info("Raw: Failed to read response header: ", err) return nil, err } if buffer[0] != this.responseHeader { log.Info("Raw: Unexpected response header. Expecting ", this.responseHeader, " but actually ", buffer[0]) return nil, transport.ErrCorruptedPacket } header := &protocol.ResponseHeader{ Option: protocol.ResponseOption(buffer[1]), } if buffer[2] != 0 { cmdId := buffer[2] dataLen := int(buffer[3]) _, err := io.ReadFull(this.responseReader, buffer[:dataLen]) if err != nil { log.Info("Raw: Failed to read response command: ", err) return nil, err } data := buffer[:dataLen] command, err := UnmarshalCommand(cmdId, data) if err == nil { header.Command = command } } return header, nil }
func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, error) { for _, rule := range this.config.Rules { if rule.Apply(dest) { return rule.Tag, nil } } if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address().IsDomain() { log.Info("Router: Looking up IP for ", dest) ipDests := this.ResolveIP(dest) if ipDests != nil { for _, ipDest := range ipDests { log.Info("Router: Trying IP ", ipDest) for _, rule := range this.config.Rules { if rule.Apply(ipDest) { return rule.Tag, nil } } } } } return "", ErrNoRuleApplicable }
func DialKCP(src v2net.Address, dest v2net.Destination) (internet.Connection, error) { udpDest := v2net.UDPDestination(dest.Address(), dest.Port()) log.Info("Dialling KCP to ", udpDest) conn, err := internet.DialToDest(src, udpDest) if err != nil { return nil, err } cpip := NewSimpleAuthenticator() conv := uint16(atomic.AddUint32(&globalConv, 1)) session := NewConnection(conv, conn, conn.LocalAddr().(*net.UDPAddr), conn.RemoteAddr().(*net.UDPAddr), cpip) session.FetchInputFrom(conn) return session, nil }