Meow
2026-06-19 06:31:21 +08:00
committed by GitHub
parent 6412738486
commit 711aea4e34
15 changed files with 208 additions and 151 deletions
+2 -27
View File
@@ -9,8 +9,6 @@ import (
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/signal/done"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
type HunkConn interface {
@@ -38,31 +36,8 @@ func NewHunkReadWriter(hc HunkConn, cancel context.CancelFunc) *HunkReaderWriter
return &HunkReaderWriter{hc, cancel, done.New(), nil, 0}
}
func NewHunkConn(hc HunkConn, cancel context.CancelFunc) net.Conn {
var rAddr net.Addr
pr, ok := peer.FromContext(hc.Context())
if ok {
rAddr = pr.Addr
} else {
rAddr = &net.TCPAddr{
IP: []byte{0, 0, 0, 0},
Port: 0,
}
}
md, ok := metadata.FromIncomingContext(hc.Context())
if ok {
header := md.Get("x-real-ip")
if len(header) > 0 {
realip := net.ParseAddress(header[0])
if realip.Family().IsIP() {
rAddr = &net.TCPAddr{
IP: realip.IP(),
Port: 0,
}
}
}
}
func NewHunkConn(hc HunkConn, cancel context.CancelFunc, trustedXForwardedFor []string) net.Conn {
rAddr := remoteAddrFromContext(hc.Context(), trustedXForwardedFor)
wrc := NewHunkReadWriter(hc, cancel)
return cnc.NewConnection(
cnc.ConnectionInput(wrc),
+3 -29
View File
@@ -3,15 +3,12 @@ package encoding
import (
"context"
"io"
"net"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
xnet "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/signal/done"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
type MultiHunkConn interface {
@@ -34,31 +31,8 @@ func NewMultiHunkReadWriter(hc MultiHunkConn, cancel context.CancelFunc) *MultiH
return &MultiHunkReaderWriter{hc, cancel, done.New(), nil}
}
func NewMultiHunkConn(hc MultiHunkConn, cancel context.CancelFunc) net.Conn {
var rAddr net.Addr
pr, ok := peer.FromContext(hc.Context())
if ok {
rAddr = pr.Addr
} else {
rAddr = &net.TCPAddr{
IP: []byte{0, 0, 0, 0},
Port: 0,
}
}
md, ok := metadata.FromIncomingContext(hc.Context())
if ok {
header := md.Get("x-real-ip")
if len(header) > 0 {
realip := xnet.ParseAddress(header[0])
if realip.Family().IsIP() {
rAddr = &net.TCPAddr{
IP: realip.IP(),
Port: 0,
}
}
}
}
func NewMultiHunkConn(hc MultiHunkConn, cancel context.CancelFunc, trustedXForwardedFor []string) net.Conn {
rAddr := remoteAddrFromContext(hc.Context(), trustedXForwardedFor)
wrc := NewMultiHunkReadWriter(hc, cancel)
return cnc.NewConnection(
cnc.ConnectionInputMulti(wrc),
@@ -0,0 +1,58 @@
package encoding
import (
"context"
"strings"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
func remoteAddrFromContext(ctx context.Context, trusted []string) net.Addr {
var remoteAddr net.Addr
if pr, ok := peer.FromContext(ctx); ok {
remoteAddr = pr.Addr
} else {
remoteAddr = &net.TCPAddr{
IP: []byte{0, 0, 0, 0},
Port: 0,
}
}
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return remoteAddr
}
if forwardedAddr := parseTrustedXForwardedFor(md, trusted, remoteAddr); forwardedAddr != nil && forwardedAddr.Family().IsIP() {
remoteAddr = &net.TCPAddr{
IP: forwardedAddr.IP(),
Port: 0,
}
}
return remoteAddr
}
func parseTrustedXForwardedFor(md metadata.MD, trusted []string, remoteAddr net.Addr) net.Address {
values := md.Get("X-Forwarded-For")
if len(values) == 0 || values[0] == "" {
return nil
}
value := values[0]
for _, t := range trusted {
if len(md.Get(t)) > 0 {
if idx := strings.IndexByte(value, ','); idx >= 0 {
value = value[:idx]
}
return net.ParseAddress(value)
}
}
if len(trusted) == 0 {
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 "X-Forwarded-For" from `, remoteAddr, `: `, value)
}
return nil
}
@@ -0,0 +1,53 @@
package encoding
import (
"context"
"net"
"testing"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
func TestRemoteAddrFromContext(t *testing.T) {
tests := []struct {
name string
metadata metadata.MD
trustedXForwardedFor []string
expectedRemoteAddress string
}{
{
name: "trust X-Forwarded-For when configured",
metadata: metadata.Pairs("X-Forwarded-For", "2.2.2.2, 3.3.3.3"),
trustedXForwardedFor: []string{"X-Forwarded-For"},
expectedRemoteAddress: "2.2.2.2:0",
},
{
name: "trust X-Forwarded-For with trusted marker",
metadata: metadata.Pairs("X-Forwarded-For", "4.4.4.4", "X-Trusted-CDN", "1"),
trustedXForwardedFor: []string{"X-Trusted-CDN"},
expectedRemoteAddress: "4.4.4.4:0",
},
{
name: "ignore X-Forwarded-For without trusted marker",
metadata: metadata.Pairs("X-Forwarded-For", "5.5.5.5"),
trustedXForwardedFor: []string{"X-Trusted-CDN"},
expectedRemoteAddress: "127.0.0.1:12345",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := peer.NewContext(metadata.NewIncomingContext(context.Background(), test.metadata), &peer.Peer{
Addr: &net.TCPAddr{
IP: net.ParseIP("127.0.0.1"),
Port: 12345,
},
})
remoteAddr := remoteAddrFromContext(ctx, test.trustedXForwardedFor)
if remoteAddr.String() != test.expectedRemoteAddress {
t.Fatalf("unexpected remote address: %s", remoteAddr.String())
}
})
}
}