This commit is contained in:
Meo597
2026-06-19 00:33:50 +08:00
parent 4ad42e6e28
commit 74d7e4f60f
5 changed files with 30 additions and 33 deletions
+11 -6
View File
@@ -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.
+16 -6
View File
@@ -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)
}
})
}
+1 -7
View File
@@ -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
}
+1 -7
View File
@@ -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 != "" {
+1 -7
View File
@@ -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))
}