From 5cf0f18c29a0bb791fafa01a74a85eb9148af6be Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 15 May 2025 10:14:18 +0800 Subject: [PATCH] feat: reality add `support-x25519mlkem768`, it only works with new version server --- adapter/outbound/reality.go | 3 +++ component/tls/reality.go | 48 ++++++++++++++++++------------------- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/adapter/outbound/reality.go b/adapter/outbound/reality.go index e5b090a8b..55d3cba9c 100644 --- a/adapter/outbound/reality.go +++ b/adapter/outbound/reality.go @@ -13,11 +13,14 @@ import ( type RealityOptions struct { PublicKey string `proxy:"public-key"` ShortID string `proxy:"short-id"` + + SupportX25519MLKEM768 bool `proxy:"support-x25519mlkem768"` } func (o RealityOptions) Parse() (*tlsC.RealityConfig, error) { if o.PublicKey != "" { config := new(tlsC.RealityConfig) + config.SupportX25519MLKEM768 = o.SupportX25519MLKEM768 const x25519ScalarSize = 32 publicKey, err := base64.RawURLEncoding.DecodeString(o.PublicKey) diff --git a/component/tls/reality.go b/component/tls/reality.go index 6a5cdc5fe..b16676f02 100644 --- a/component/tls/reality.go +++ b/component/tls/reality.go @@ -35,6 +35,8 @@ const RealityMaxShortIDLen = 8 type RealityConfig struct { PublicKey *ecdh.PublicKey ShortID [RealityMaxShortIDLen]byte + + SupportX25519MLKEM768 bool } func GetRealityConn(ctx context.Context, conn net.Conn, fingerprint UClientHelloID, tlsConfig *tls.Config, realityConfig *RealityConfig) (net.Conn, error) { @@ -48,38 +50,36 @@ func GetRealityConn(ctx context.Context, conn net.Conn, fingerprint UClientHello SessionTicketsDisabled: true, VerifyPeerCertificate: verifier.VerifyPeerCertificate, } - clientID := utls.ClientHelloID{ - Client: fingerprint.Client, - Version: fingerprint.Version, - Seed: fingerprint.Seed, - } - uConn := utls.UClient(conn, uConfig, clientID) + + uConn := utls.UClient(conn, uConfig, fingerprint) verifier.UConn = uConn err := uConn.BuildHandshakeState() if err != nil { return nil, err } - // ------for X25519MLKEM768 does not work properly with reality------- - // Iterate over extensions and check - for _, extension := range uConn.Extensions { - if ce, ok := extension.(*utls.SupportedCurvesExtension); ok { - ce.Curves = slices.DeleteFunc(ce.Curves, func(curveID utls.CurveID) bool { - return curveID == utls.X25519MLKEM768 - }) + if !realityConfig.SupportX25519MLKEM768 { + // ------for X25519MLKEM768 does not work properly with the old reality server------- + // Iterate over extensions and check + for _, extension := range uConn.Extensions { + if ce, ok := extension.(*utls.SupportedCurvesExtension); ok { + ce.Curves = slices.DeleteFunc(ce.Curves, func(curveID utls.CurveID) bool { + return curveID == utls.X25519MLKEM768 + }) + } + if ks, ok := extension.(*utls.KeyShareExtension); ok { + ks.KeyShares = slices.DeleteFunc(ks.KeyShares, func(share utls.KeyShare) bool { + return share.Group == utls.X25519MLKEM768 + }) + } } - if ks, ok := extension.(*utls.KeyShareExtension); ok { - ks.KeyShares = slices.DeleteFunc(ks.KeyShares, func(share utls.KeyShare) bool { - return share.Group == utls.X25519MLKEM768 - }) + // Rebuild the client hello + err = uConn.BuildHandshakeState() + if err != nil { + return nil, err } + // -------------------------------------------------------------------- } - // Rebuild the client hello - err = uConn.BuildHandshakeState() - if err != nil { - return nil, err - } - // -------------------------------------------------------------------- hello := uConn.HandshakeState.Hello rawSessionID := hello.Raw[39 : 39+32] // the location of session ID @@ -144,7 +144,7 @@ func GetRealityConn(ctx context.Context, conn net.Conn, fingerprint UClientHello log.Debugln("REALITY Authentication: %v, AEAD: %T", verifier.verified, aeadCipher) if !verifier.verified { - go realityClientFallback(uConn, uConfig.ServerName, clientID) + go realityClientFallback(uConn, uConfig.ServerName, fingerprint) return nil, errors.New("REALITY authentication failed") } diff --git a/go.mod b/go.mod index a4ecb0fbd..b378a23fb 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20250503055512-501391591dee github.com/metacubex/tfo-go v0.0.0-20250503140532-decbcfccbfdf - github.com/metacubex/utls v1.7.0-alpha.3 + github.com/metacubex/utls v1.7.3 github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20 github.com/mroth/weightedrand/v2 v2.1.0 diff --git a/go.sum b/go.sum index 0840c49a4..890d1712d 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113a github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= github.com/metacubex/tfo-go v0.0.0-20250503140532-decbcfccbfdf h1:LwID1wz4tzypidd412dd4dC1H0m1TgRCQ/XvRvMJDFM= github.com/metacubex/tfo-go v0.0.0-20250503140532-decbcfccbfdf/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= -github.com/metacubex/utls v1.7.0-alpha.3 h1:cp1cEMUnoifiWrGHRzo+nCwPRveN9yPD8QaRFmfcYxA= -github.com/metacubex/utls v1.7.0-alpha.3/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU= +github.com/metacubex/utls v1.7.3 h1:yDcMEWojFh+t8rU9X0HPcZDPAoFze/rIIyssqivzj8A= +github.com/metacubex/utls v1.7.3/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU= github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ= github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=