diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index 5433ef6a6..27186f78f 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -210,7 +210,7 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn } if isStream, err := packetaddr.GetDestinationSubsetOf(dest); err == nil { - packetConn, err := internet.ListenSystemPacket(ctx, nil, h.streamSettings.SocketSettings) + packetConn, err := internet.ListenSystemPacket(ctx, &net.UDPAddr{IP: net.AnyIP.IP(), Port: 0}, h.streamSettings.SocketSettings) if err != nil { return nil, newError("unable to listen socket").Base(err) } diff --git a/common/net/packetaddr/connection_adaptor.go b/common/net/packetaddr/connection_adaptor.go index a88f7f8bf..429fc9c2f 100644 --- a/common/net/packetaddr/connection_adaptor.go +++ b/common/net/packetaddr/connection_adaptor.go @@ -64,19 +64,23 @@ func (c *packetConnectionAdaptor) ReadFrom(p []byte) (n int, addr gonet.Addr, er defer c.readerAccess.Unlock() if c.readerBuffer.IsEmpty() { c.readerBuffer, err = c.link.Reader.ReadMultiBuffer() + if err != nil { + return 0, nil, err + } } c.readerBuffer, n = buf.SplitFirstBytes(c.readerBuffer, p) - p, addr = ExtractAddressFromPacket(p) + var w []byte + w, addr = ExtractAddressFromPacket(p[:n]) + n = copy(p, w) return } func (c *packetConnectionAdaptor) WriteTo(p []byte, addr gonet.Addr) (n int, err error) { payloadLen := len(p) p = AttachAddressToPacket(p, addr) - buffer := buf.New() + buffer := buf.FromBytes(p) mb := buf.MultiBuffer{buffer} err = c.link.Writer.WriteMultiBuffer(mb) - buf.ReleaseMulti(mb) if err != nil { return 0, err } @@ -128,7 +132,7 @@ func (pc *packetConnWrapper) Read(p []byte) (n int, err error) { recbuf.Extend(2048) n, addr, err := pc.PacketConn.ReadFrom(recbuf.Bytes()) if err != nil { - return 0, nil + return 0, err } result := AttachAddressToPacket(recbuf.Bytes()[0:n], addr) n = copy(p, result) @@ -146,7 +150,7 @@ func (pc *packetConnWrapper) Write(p []byte) (n int, err error) { } func (pc *packetConnWrapper) Close() error { - return pc.Close() + return pc.PacketConn.Close() } func GetDestinationSubsetOf(dest net.Destination) (bool, error) { diff --git a/proxy/socks/protocol.go b/proxy/socks/protocol.go index 9ab6a805e..33eb89516 100644 --- a/proxy/socks/protocol.go +++ b/proxy/socks/protocol.go @@ -359,6 +359,17 @@ func EncodeUDPPacket(request *protocol.RequestHeader, data []byte) (*buf.Buffer, return b, nil } +func EncodeUDPPacketFromAddress(address net.Destination, data []byte) (*buf.Buffer, error) { + b := buf.New() + common.Must2(b.Write([]byte{0, 0, 0 /* Fragment */})) + if err := addrParser.WriteAddressPort(b, address.Address, address.Port); err != nil { + b.Release() + return nil, err + } + common.Must2(b.Write(data)) + return b, nil +} + type UDPReader struct { reader io.Reader } diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 2cf0d82ef..a7937179d 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -200,10 +200,13 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection, newError("writing back UDP response with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx)) request := protocol.RequestHeaderFromContext(ctx) + var packetSource net.Destination if request == nil { - return + packetSource = packet.Source + } else { + packetSource = net.UDPDestination(request.Address, request.Port) } - udpMessage, err := EncodeUDPPacket(request, payload.Bytes()) + udpMessage, err := EncodeUDPPacketFromAddress(packetSource, payload.Bytes()) payload.Release() defer udpMessage.Release()