Skip to content

Commit 89ff515

Browse files
committed
feat: support X-Forwarded-For in gRPC transport
1 parent 8fed55f commit 89ff515

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

common/protocol/grpc/metadata.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package grpc
2+
3+
import (
4+
"strings"
5+
6+
"google.golang.org/grpc/metadata"
7+
8+
"github.com/v2fly/v2ray-core/v4/common/net"
9+
)
10+
11+
// ParseXForwardedFor parses X-Forwarded-For metadata in gRPC metadata, and return the IP list in it.
12+
func ParseXForwardedFor(md metadata.MD) []net.Address {
13+
xff := md.Get("X-Forwarded-For")
14+
if len(xff) == 0 {
15+
return nil
16+
}
17+
list := strings.Split(xff[0], ",")
18+
addrs := make([]net.Address, 0, len(list))
19+
for _, proxy := range list {
20+
addrs = append(addrs, net.ParseAddress(proxy))
21+
}
22+
return addrs
23+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package grpc_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/google/go-cmp/cmp"
7+
"google.golang.org/grpc/metadata"
8+
9+
"github.com/v2fly/v2ray-core/v4/common/net"
10+
. "github.com/v2fly/v2ray-core/v4/common/protocol/grpc"
11+
)
12+
13+
func TestParseXForwardedFor(t *testing.T) {
14+
md := metadata.Pairs("X-Forwarded-For", "129.78.138.66, 129.78.64.103")
15+
addrs := ParseXForwardedFor(md)
16+
if r := cmp.Diff(addrs, []net.Address{net.ParseAddress("129.78.138.66"), net.ParseAddress("129.78.64.103")}); r != "" {
17+
t.Error(r)
18+
}
19+
}

transport/internet/grpc/encoding/conn.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import (
99
"net"
1010
"time"
1111

12+
"google.golang.org/grpc/metadata"
1213
"google.golang.org/grpc/peer"
14+
15+
grpc_proto "github.com/v2fly/v2ray-core/v4/common/protocol/grpc"
1316
)
1417

1518
// GunService is the abstract interface of GunService_TunClient and GunService_TunServer
@@ -108,6 +111,16 @@ func NewGunConn(service GunService, over context.CancelFunc) *GunConn {
108111
Port: 0,
109112
}
110113
}
114+
if _, isServer := service.(*gunServiceTunServer); isServer {
115+
if md, ok := metadata.FromIncomingContext(service.Context()); ok {
116+
if forwardedAddrs := grpc_proto.ParseXForwardedFor(md); len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() {
117+
conn.remote = &net.TCPAddr{
118+
IP: forwardedAddrs[0].IP(),
119+
Port: int(0),
120+
}
121+
}
122+
}
123+
}
111124

112125
return conn
113126
}

0 commit comments

Comments
 (0)