Procházet zdrojové kódy

gRPC client: Strip "grpc-go/version" suffix from User-Agent header (#5689)

Fixes https://github.com/XTLS/Xray-core/pull/5658#issuecomment-3894269376

---------

Co-authored-by: RPRX <[email protected]>
Copilot před 4 měsíci
rodič
revize
b43276c6d3

+ 12 - 0
transport/internet/grpc/config_test.go

@@ -1,9 +1,12 @@
 package grpc
 package grpc
 
 
 import (
 import (
+	"reflect"
 	"testing"
 	"testing"
 
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/assert"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
 )
 )
 
 
 func TestConfig_GetServiceName(t *testing.T) {
 func TestConfig_GetServiceName(t *testing.T) {
@@ -115,3 +118,12 @@ func TestConfig_GetTunMultiStreamName(t *testing.T) {
 		})
 		})
 	}
 	}
 }
 }
+
+func TestSetUserAgent(t *testing.T) {
+	ua := "Test/1.0"
+	conn, err := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithUserAgent(ua))
+	assert.NoError(t, err)
+	defer conn.Close()
+	setUserAgent(conn, ua)
+	assert.Equal(t, ua, reflect.ValueOf(conn).Elem().FieldByName("dopts").FieldByName("copts").FieldByName("UserAgent").String())
+}

+ 19 - 8
transport/internet/grpc/dial.go

@@ -2,6 +2,7 @@ package grpc
 
 
 import (
 import (
 	"context"
 	"context"
+	"reflect"
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
@@ -168,12 +169,6 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
 		dialOptions = append(dialOptions, grpc.WithInitialWindowSize(grpcSettings.InitialWindowsSize))
 		dialOptions = append(dialOptions, grpc.WithInitialWindowSize(grpcSettings.InitialWindowsSize))
 	}
 	}
 
 
-	userAgent := grpcSettings.UserAgent
-	if userAgent == "" {
-		userAgent = utils.ChromeUA
-	}
-	dialOptions = append(dialOptions, grpc.WithUserAgent(userAgent))
-
 	var grpcDestHost string
 	var grpcDestHost string
 	if dest.Address.Family().IsDomain() {
 	if dest.Address.Family().IsDomain() {
 		grpcDestHost = dest.Address.Domain()
 		grpcDestHost = dest.Address.Domain()
@@ -181,10 +176,26 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
 		grpcDestHost = dest.Address.IP().String()
 		grpcDestHost = dest.Address.IP().String()
 	}
 	}
 
 
-	conn, err := grpc.Dial(
-		net.JoinHostPort(grpcDestHost, dest.Port.String()),
+	conn, err := grpc.NewClient(
+		"passthrough:///"+net.JoinHostPort(grpcDestHost, dest.Port.String()),
 		dialOptions...,
 		dialOptions...,
 	)
 	)
+	if err == nil {
+		userAgent := grpcSettings.UserAgent
+		if userAgent == "" {
+			userAgent = utils.ChromeUA
+		}
+		setUserAgent(conn, userAgent)
+		conn.Connect()
+	}
 	globalDialerMap[dialerConf{dest, streamSettings}] = conn
 	globalDialerMap[dialerConf{dest, streamSettings}] = conn
 	return conn, err
 	return conn, err
 }
 }
+
+// setUserAgent overrides the user-agent on a ClientConn to remove the
+// "grpc-go/version" suffix that grpc.WithUserAgent unconditionally appends.
+func setUserAgent(conn *grpc.ClientConn, ua string) {
+	if f := reflect.ValueOf(conn).Elem().FieldByName("dopts").FieldByName("copts").FieldByName("UserAgent"); f.IsValid() {
+		*(*string)(f.Addr().UnsafePointer()) = ua
+	}
+}