This commit is contained in:
Meo597
2026-06-19 00:11:07 +08:00
parent ce3b4fd175
commit 4ad42e6e28
7 changed files with 45 additions and 118 deletions
+7 -21
View File
@@ -11,38 +11,24 @@ import (
"github.com/xtls/xray-core/common/net"
)
func parseXForwardedFor(xff string) []net.Address {
list := strings.Split(xff, ",")
addrs := make([]net.Address, 0, len(list))
for _, proxy := range list {
addrs = append(addrs, net.ParseAddress(proxy))
}
return addrs
}
// ParseTrustedXForwardedFor parses forwarding headers only when a configured trusted header is present.
func ParseTrustedXForwardedFor(header http.Header, trusted []string, clientAddr gonet.Addr) []net.Address {
key := "X-Real-IP"
value := header.Get(key)
if value == "" {
key = "X-Forwarded-For"
value = header.Get(key)
}
func ParseTrustedXForwardedFor(header http.Header, trusted []string, remoteAddr gonet.Addr) net.Address {
value := header.Get("X-Forwarded-For")
if value == "" {
return nil
}
for _, t := range trusted {
if len(header.Values(t)) > 0 {
if key == "X-Real-IP" {
return []net.Address{net.ParseAddress(value)}
if idx := strings.IndexByte(value, ','); idx >= 0 {
value = value[:idx]
}
return parseXForwardedFor(value)
return net.ParseAddress(value)
}
}
if len(trusted) == 0 {
errors.LogWarning(context.Background(), `received "`, key, `" from `, clientAddr, ` but "sockopt.trustedXForwardedFor" is not configured; ignoring it and using the real remote address`)
errors.LogWarning(context.Background(), `received "X-Forwarded-For" from `, remoteAddr, ` but "sockopt.trustedXForwardedFor" is not configured; ignoring it and using the real remote address`)
} else {
errors.LogError(context.Background(), `ignored potentially forged "`, key, `" from `, clientAddr, `: `, value)
errors.LogError(context.Background(), `ignored potentially forged "X-Forwarded-For" from `, remoteAddr, `: `, value)
}
return nil
}
+6 -30
View File
@@ -7,21 +7,20 @@ import (
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
. "github.com/xtls/xray-core/common/protocol/http"
)
func TestParseTrustedXForwardedFor(t *testing.T) {
clientAddr := &gonet.TCPAddr{IP: gonet.ParseIP("127.0.0.1"), Port: 12345}
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 addrs := ParseTrustedXForwardedFor(header, nil, clientAddr); addrs != nil {
t.Fatalf("unexpected trusted X-Forwarded-For: %v", addrs)
if addr := ParseTrustedXForwardedFor(header, nil, remoteAddr); addr != nil {
t.Fatalf("unexpected trusted X-Forwarded-For: %v", addr)
}
})
@@ -30,32 +29,9 @@ func TestParseTrustedXForwardedFor(t *testing.T) {
header.Add("X-Forwarded-For", "129.78.138.66, 129.78.64.103")
header.Add("X-Trusted-CDN", "")
addrs := ParseTrustedXForwardedFor(header, []string{"X-Trusted-CDN"}, clientAddr)
if r := cmp.Diff(addrs, []net.Address{net.ParseAddress("129.78.138.66"), net.ParseAddress("129.78.64.103")}); r != "" {
t.Error(r)
}
})
t.Run("prefer X-Real-IP over X-Forwarded-For", func(t *testing.T) {
header := http.Header{}
header.Add("X-Real-IP", "10.0.0.1")
header.Add("X-Forwarded-For", "129.78.138.66, 129.78.64.103")
header.Add("X-Trusted-CDN", "")
addrs := ParseTrustedXForwardedFor(header, []string{"X-Trusted-CDN"}, clientAddr)
if r := cmp.Diff(addrs, []net.Address{net.ParseAddress("10.0.0.1")}); r != "" {
t.Error(r)
}
})
t.Run("do not parse X-Real-IP as a list", func(t *testing.T) {
header := http.Header{}
header.Add("X-Real-IP", "8.8.8.8, 9.9.9.9")
header.Add("X-Trusted-CDN", "")
addrs := ParseTrustedXForwardedFor(header, []string{"X-Trusted-CDN"}, clientAddr)
if r := cmp.Diff(addrs, []net.Address{net.ParseAddress("8.8.8.8, 9.9.9.9")}); r != "" {
t.Error(r)
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)
}
})
}