Browse Source

Add quic fingerprints and preset configs

yuhan6665 1 year ago
parent
commit
091725fd5d

+ 9 - 0
transport/internet/http/dialer.go

@@ -120,6 +120,15 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
 			},
 		}
 		transport = roundTripper
+
+		if fingerprint := tls.GetQuicFingerprint(tlsConfigs.Fingerprint); fingerprint != nil {
+			quicSpec, err := quic.QUICID2Spec(*fingerprint)
+			if err != nil {
+				errors.LogError(ctx, "unknown fingerprint: ", tlsConfigs.Fingerprint)
+			} else {
+				transport = http3.GetURoundTripper(roundTripper, &quicSpec, nil)
+			}
+		}
 	} else {
 		transportH2 := &http2.Transport{
 			DialTLSContext: func(hctx context.Context, string, addr string, tlsConfig *gotls.Config) (net.Conn, error) {

+ 12 - 3
transport/internet/splithttp/dialer.go

@@ -73,7 +73,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
 		}
 
 		muxManager = NewMuxManager(mux, func() interface{} {
-			return createHTTPClient(dest, streamSettings)
+			return createHTTPClient(ctx, dest, streamSettings)
 		})
 		globalDialerMap[key] = muxManager
 	}
@@ -82,7 +82,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
 	return res.Resource.(DialerClient), res
 }
 
-func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStreamConfig) DialerClient {
+func createHTTPClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) DialerClient {
 	tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
 	realityConfig := reality.ConfigFromStreamSettings(streamSettings)
 
@@ -145,7 +145,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
 			MaxIncomingStreams: -1,
 			KeepAlivePeriod:    h3KeepalivePeriod,
 		}
-		transport = &http3.RoundTripper{
+		roundTripper := &http3.RoundTripper{
 			QuicConfig:      quicConfig,
 			TLSClientConfig: tls.CopyConfig(gotlsConfig),
 			Dial: func(ctx context.Context, addr string, tlsCfg *utls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
@@ -185,6 +185,15 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
 				return quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg)
 			},
 		}
+		transport = roundTripper
+		if fingerprint := tls.GetQuicFingerprint(tlsConfig.Fingerprint); fingerprint != nil {
+			quicSpec, err := quic.QUICID2Spec(*fingerprint)
+			if err != nil {
+				errors.LogError(ctx, "unknown fingerprint: ", tlsConfig.Fingerprint)
+			} else {
+				transport = http3.GetURoundTripper(roundTripper, &quicSpec, nil)
+			}
+		}
 	} else if isH2 {
 		transport = &http2.Transport{
 			DialTLSContext: func(ctxInner context.Context, network string, addr string, cfg *gotls.Config) (net.Conn, error) {

+ 42 - 0
transport/internet/tls/tls.go

@@ -7,6 +7,7 @@ import (
 	"math/big"
 	"time"
 
+	"github.com/refraction-networking/uquic"
 	utls "github.com/refraction-networking/utls"
 	"github.com/xtls/xray-core/common/buf"
 	"github.com/xtls/xray-core/common/net"
@@ -154,6 +155,18 @@ func init() {
 		}
 		i++
 	}
+
+	bigInt, _ = rand.Int(rand.Reader, big.NewInt(int64(len(QuicAllFingerprints))))
+	stopAt = int(bigInt.Int64())
+	i = 0
+	for _, v := range QuicAllFingerprints {
+		if i == stopAt {
+			QuicPresetFingerprints["random"] = v
+			break
+		}
+		i++
+	}
+
 	weights := utls.DefaultWeights
 	weights.TLSVersMax_Set_VersionTLS13 = 1
 	weights.FirstKeyShare_Set_CurveP256 = 0
@@ -179,6 +192,35 @@ func GetFingerprint(name string) (fingerprint *utls.ClientHelloID) {
 	return
 }
 
+func GetQuicFingerprint(name string) (fingerprint *quic.QUICID) {
+	if name == "" {
+		return
+	}
+	if fingerprint = QuicPresetFingerprints[name]; fingerprint != nil {
+		return
+	}
+	if fingerprint = QuicAllFingerprints[name]; fingerprint != nil {
+		return
+	}
+	return
+}
+
+var QuicPresetFingerprints = map[string]*quic.QUICID {
+	"chrome":     &quic.QUICChrome_115,
+	"firefox":    &quic.QUICFirefox_116,
+	"random":     nil,
+}
+
+var QuicAllFingerprints = map[string]*quic.QUICID {
+	"quicchrome_115":      &quic.QUICChrome_115,
+	"quicchrome_115_ipv4": &quic.QUICChrome_115_IPv4,
+	"quicchrome_115_ipv6": &quic.QUICChrome_115_IPv6,
+	"quicfirefox_116":     &quic.QUICFirefox_116,
+	"quicfirefox_116a":    &quic.QUICFirefox_116A,
+	"quicfirefox_116b":    &quic.QUICFirefox_116B,
+	"quicfirefox_116c":    &quic.QUICFirefox_116C,
+}
+
 var PresetFingerprints = map[string]*utls.ClientHelloID{
 	// Recommended preset options in GUI clients
 	"chrome":     &utls.HelloChrome_Auto,