From 74d7e4f60f774ee442dd992a5dd7d6752b4c0354 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Fri, 19 Jun 2026 00:33:50 +0800 Subject: [PATCH] refine --- common/protocol/http/headers.go | 17 +++++++++++------ common/protocol/http/headers_test.go | 22 ++++++++++++++++------ transport/internet/httpupgrade/hub.go | 8 +------- transport/internet/splithttp/hub.go | 8 +------- transport/internet/websocket/hub.go | 8 +------- 5 files changed, 30 insertions(+), 33 deletions(-) diff --git a/common/protocol/http/headers.go b/common/protocol/http/headers.go index e28bbebba..61a07005c 100644 --- a/common/protocol/http/headers.go +++ b/common/protocol/http/headers.go @@ -2,7 +2,6 @@ package http import ( "context" - gonet "net" "net/http" "strconv" "strings" @@ -11,18 +10,24 @@ import ( "github.com/xtls/xray-core/common/net" ) -// ParseTrustedXForwardedFor parses forwarding headers only when a configured trusted header is present. -func ParseTrustedXForwardedFor(header http.Header, trusted []string, remoteAddr gonet.Addr) net.Address { +// ApplyTrustedXForwardedFor returns remoteAddr overridden by X-Forwarded-For only when a configured trusted header is present. +func ApplyTrustedXForwardedFor(header http.Header, trusted []string, remoteAddr net.Addr) net.Addr { value := header.Get("X-Forwarded-For") if value == "" { - return nil + return remoteAddr } for _, t := range trusted { if len(header.Values(t)) > 0 { if idx := strings.IndexByte(value, ','); idx >= 0 { value = value[:idx] } - return net.ParseAddress(value) + if addr := net.ParseAddress(value); addr.Family().IsIP() { + return &net.TCPAddr{ + IP: addr.IP(), + Port: 0, + } + } + return remoteAddr } } if len(trusted) == 0 { @@ -30,7 +35,7 @@ func ParseTrustedXForwardedFor(header http.Header, trusted []string, remoteAddr } else { errors.LogError(context.Background(), `ignored potentially forged "X-Forwarded-For" from `, remoteAddr, `: `, value) } - return nil + return remoteAddr } // RemoveHopByHopHeaders removes hop by hop headers in http header list. diff --git a/common/protocol/http/headers_test.go b/common/protocol/http/headers_test.go index 21f1d1e62..bad395d0c 100644 --- a/common/protocol/http/headers_test.go +++ b/common/protocol/http/headers_test.go @@ -12,15 +12,15 @@ import ( . "github.com/xtls/xray-core/common/protocol/http" ) -func TestParseTrustedXForwardedFor(t *testing.T) { +func TestApplyTrustedXForwardedFor(t *testing.T) { remoteAddr := &gonet.TCPAddr{IP: gonet.ParseIP("127.0.0.1"), Port: 12345} t.Run("ignore X-Forwarded-For without trusted header", func(t *testing.T) { header := http.Header{} header.Add("X-Forwarded-For", "129.78.138.66, 129.78.64.103") - if addr := ParseTrustedXForwardedFor(header, nil, remoteAddr); addr != nil { - t.Fatalf("unexpected trusted X-Forwarded-For: %v", addr) + if addr := ApplyTrustedXForwardedFor(header, nil, remoteAddr); addr != remoteAddr { + t.Fatalf("unexpected remote address: %v", addr) } }) @@ -29,9 +29,19 @@ func TestParseTrustedXForwardedFor(t *testing.T) { header.Add("X-Forwarded-For", "129.78.138.66, 129.78.64.103") header.Add("X-Trusted-CDN", "") - addr := ParseTrustedXForwardedFor(header, []string{"X-Trusted-CDN"}, remoteAddr) - if addr != net.ParseAddress("129.78.138.66") { - t.Fatalf("unexpected trusted X-Forwarded-For: %v", addr) + addr := ApplyTrustedXForwardedFor(header, []string{"X-Trusted-CDN"}, remoteAddr) + if addr.String() != "129.78.138.66:0" { + t.Fatalf("unexpected remote address: %v", addr) + } + }) + + t.Run("ignore non-IP X-Forwarded-For", func(t *testing.T) { + header := http.Header{} + header.Add("X-Forwarded-For", "example.com") + header.Add("X-Trusted-CDN", "") + + if addr := ApplyTrustedXForwardedFor(header, []string{"X-Trusted-CDN"}, remoteAddr); addr != remoteAddr { + t.Fatalf("unexpected remote address: %v", addr) } }) } diff --git a/transport/internet/httpupgrade/hub.go b/transport/internet/httpupgrade/hub.go index 720fc14a6..cb9a79d9a 100644 --- a/transport/internet/httpupgrade/hub.go +++ b/transport/internet/httpupgrade/hub.go @@ -85,13 +85,7 @@ func (s *server) upgrade(conn net.Conn) (stat.Connection, error) { if s.socketSettings != nil { trustedXFF = s.socketSettings.TrustedXForwardedFor } - forwardedAddr := http_proto.ParseTrustedXForwardedFor(req.Header, trustedXFF, remoteAddr) - if forwardedAddr != nil && forwardedAddr.Family().IsIP() { - remoteAddr = &net.TCPAddr{ - IP: forwardedAddr.IP(), - Port: int(0), - } - } + remoteAddr = http_proto.ApplyTrustedXForwardedFor(req.Header, trustedXFF, remoteAddr) return stat.Connection(newConnection(conn, remoteAddr)), nil } diff --git a/transport/internet/splithttp/hub.go b/transport/internet/splithttp/hub.go index eb89c7d83..a28866cf9 100644 --- a/transport/internet/splithttp/hub.go +++ b/transport/internet/splithttp/hub.go @@ -174,13 +174,7 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req if h.socketSettings != nil { trustedXFF = h.socketSettings.TrustedXForwardedFor } - forwardedAddr := http_proto.ParseTrustedXForwardedFor(request.Header, trustedXFF, remoteAddr) - if forwardedAddr != nil && forwardedAddr.Family().IsIP() { - remoteAddr = &net.TCPAddr{ - IP: forwardedAddr.IP(), - Port: 0, - } - } + remoteAddr = http_proto.ApplyTrustedXForwardedFor(request.Header, trustedXFF, remoteAddr) var currentSession *httpSession if sessionId != "" { diff --git a/transport/internet/websocket/hub.go b/transport/internet/websocket/hub.go index c4c81d6cd..42dba880f 100644 --- a/transport/internet/websocket/hub.go +++ b/transport/internet/websocket/hub.go @@ -70,13 +70,7 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req if h.socketSettings != nil { trustedXFF = h.socketSettings.TrustedXForwardedFor } - forwardedAddr := http_proto.ParseTrustedXForwardedFor(request.Header, trustedXFF, remoteAddr) - if forwardedAddr != nil && forwardedAddr.Family().IsIP() { - remoteAddr = &net.TCPAddr{ - IP: forwardedAddr.IP(), - Port: int(0), - } - } + remoteAddr = http_proto.ApplyTrustedXForwardedFor(request.Header, trustedXFF, remoteAddr) h.ln.addConn(NewConnection(conn, remoteAddr, extraReader, h.ln.config.HeartbeatPeriod)) }