From df25e33ab3f364d751374079c5dd8103f588986c Mon Sep 17 00:00:00 2001 From: Fangliding Date: Sun, 14 Jun 2026 20:02:26 +0800 Subject: [PATCH 1/6] Fix panic in illegal request --- proxy/socks/protocol.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/proxy/socks/protocol.go b/proxy/socks/protocol.go index bf4f61a5b762..8d3fa2680282 100644 --- a/proxy/socks/protocol.go +++ b/proxy/socks/protocol.go @@ -196,6 +196,9 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Co var tempUDPConn *TempUDPConn //nolint:gocritic // Use if else chain for clarity if request.Command == protocol.RequestCommandUDP { + if request.Address.Family().IsDomain() { + return nil, nil, errors.New("domain name in UDP associate is illegal") + } if s.config.Address != nil { // Use configured IP as remote address in the response to UDP Associate responseAddress = s.config.Address.AsAddress() @@ -212,8 +215,8 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Co if request.Address.IP().IsUnspecified() { expectedRemote.IP = writer.RemoteAddr().(*net.TCPAddr).IP // unix? } else { - expectedRemote.IP = request.Address.IP() // panic? - expectedRemote.Port = int(request.Port) // 0 is allowed + expectedRemote.IP = request.Address.IP() + expectedRemote.Port = int(request.Port) // 0 is allowed } tempUDPConn = NewTempUDPConn(udpHub, writer, expectedRemote) } From b4cfe4f12239491a9641316ab1f719998a92d91d Mon Sep 17 00:00:00 2001 From: Fangliding Date: Wed, 17 Jun 2026 20:27:26 +0800 Subject: [PATCH 2/6] chore --- proxy/socks/protocol.go | 7 +++---- proxy/socks/server.go | 13 ++++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/proxy/socks/protocol.go b/proxy/socks/protocol.go index 8d3fa2680282..a10dde346173 100644 --- a/proxy/socks/protocol.go +++ b/proxy/socks/protocol.go @@ -196,9 +196,6 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Co var tempUDPConn *TempUDPConn //nolint:gocritic // Use if else chain for clarity if request.Command == protocol.RequestCommandUDP { - if request.Address.Family().IsDomain() { - return nil, nil, errors.New("domain name in UDP associate is illegal") - } if s.config.Address != nil { // Use configured IP as remote address in the response to UDP Associate responseAddress = s.config.Address.AsAddress() @@ -212,7 +209,9 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Co } responsePort = net.Port(udpHub.LocalAddr().(*net.UDPAddr).Port) expectedRemote := &gonet.UDPAddr{} - if request.Address.IP().IsUnspecified() { + // if request address is a domain(udp associate should not have request domain) + // treat it as unspecified + if request.Address.Family().IsDomain() || request.Address.IP().IsUnspecified() { expectedRemote.IP = writer.RemoteAddr().(*net.TCPAddr).IP // unix? } else { expectedRemote.IP = request.Address.IP() diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 53049dfe2342..02e2d421ed93 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -4,6 +4,7 @@ import ( "context" goerrors "errors" "io" + "sync" "time" "github.com/xtls/xray-core/common" @@ -216,18 +217,24 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis defer udpServer.RemoveRay() inbound := session.InboundFromContext(ctx) - if inbound != nil && inbound.Source.IsValid() { - errors.LogInfo(ctx, "client UDP connection from ", inbound.Source) - } var dest *net.Destination reader := buf.NewPacketReader(conn) + var changeRemote sync.Once for { mpayload, err := reader.ReadMultiBuffer() if err != nil { return err } + changeRemote.Do(func() { + if inbound != nil { + // change source to real remote UDP address + inbound.Source = net.DestinationFromAddr(conn.RemoteAddr()) + inbound.Local = net.DestinationFromAddr(conn.LocalAddr()) + errors.LogInfo(ctx, "client UDP connection from ", inbound.Source) + } + }) for _, payload := range mpayload { request, err := DecodeUDPPacket(payload) From 325b57dc2424121bd13b0752c41248c55f283b69 Mon Sep 17 00:00:00 2001 From: Fangliding Date: Wed, 17 Jun 2026 20:53:43 +0800 Subject: [PATCH 3/6] copy inbound --- proxy/socks/server.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 02e2d421ed93..576387c79347 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -229,10 +229,13 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis } changeRemote.Do(func() { if inbound != nil { + newInbound := *inbound // change source to real remote UDP address - inbound.Source = net.DestinationFromAddr(conn.RemoteAddr()) - inbound.Local = net.DestinationFromAddr(conn.LocalAddr()) - errors.LogInfo(ctx, "client UDP connection from ", inbound.Source) + newInbound.Source = net.DestinationFromAddr(conn.RemoteAddr()) + newInbound.Local = net.DestinationFromAddr(conn.LocalAddr()) + inbound = &newInbound + ctx = session.ContextWithInbound(ctx, &newInbound) + errors.LogInfo(ctx, "client UDP connection from ", newInbound.Source) } }) From c07f7f94cbe11cee02826b3a18cbef4e5dcd260d Mon Sep 17 00:00:00 2001 From: RPRX <63339210+RPRX@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:08:35 +0000 Subject: [PATCH 4/6] Update protocol.go --- proxy/socks/protocol.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/proxy/socks/protocol.go b/proxy/socks/protocol.go index a10dde346173..8f2030476a46 100644 --- a/proxy/socks/protocol.go +++ b/proxy/socks/protocol.go @@ -209,8 +209,6 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Co } responsePort = net.Port(udpHub.LocalAddr().(*net.UDPAddr).Port) expectedRemote := &gonet.UDPAddr{} - // if request address is a domain(udp associate should not have request domain) - // treat it as unspecified if request.Address.Family().IsDomain() || request.Address.IP().IsUnspecified() { expectedRemote.IP = writer.RemoteAddr().(*net.TCPAddr).IP // unix? } else { From 8916151f8b9fc4c95594a2e0bde6e27c789cd74f Mon Sep 17 00:00:00 2001 From: RPRX <63339210+RPRX@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:13:48 +0000 Subject: [PATCH 5/6] Update protocol.go --- proxy/socks/protocol.go | 1 + 1 file changed, 1 insertion(+) diff --git a/proxy/socks/protocol.go b/proxy/socks/protocol.go index 8f2030476a46..5d4cfd9d9b34 100644 --- a/proxy/socks/protocol.go +++ b/proxy/socks/protocol.go @@ -209,6 +209,7 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Co } responsePort = net.Port(udpHub.LocalAddr().(*net.UDPAddr).Port) expectedRemote := &gonet.UDPAddr{} + // UDP Associate should not specify a domain as source IP if request.Address.Family().IsDomain() || request.Address.IP().IsUnspecified() { expectedRemote.IP = writer.RemoteAddr().(*net.TCPAddr).IP // unix? } else { From bb977280e7203d40b237859ff1f7f94d6aba0be5 Mon Sep 17 00:00:00 2001 From: RPRX <63339210+RPRX@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:16:04 +0000 Subject: [PATCH 6/6] Update server.go --- proxy/socks/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 576387c79347..e1d34a60b7f6 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -234,8 +234,8 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis newInbound.Source = net.DestinationFromAddr(conn.RemoteAddr()) newInbound.Local = net.DestinationFromAddr(conn.LocalAddr()) inbound = &newInbound - ctx = session.ContextWithInbound(ctx, &newInbound) - errors.LogInfo(ctx, "client UDP connection from ", newInbound.Source) + ctx = session.ContextWithInbound(ctx, inbound) + errors.LogInfo(ctx, "client UDP connection from ", inbound.Source) } })