From fd9ef704b45f2bd9812d43b0a348ecedff4b4f72 Mon Sep 17 00:00:00 2001 From: YUNRU Date: Thu, 18 Jul 2024 01:49:56 +0800 Subject: [PATCH 1/7] SplitHTTP: Client supports uQUIC --- go.mod | 4 ++ go.sum | 11 +++++ transport/internet/splithttp/dialer.go | 58 ++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index e60acb4ce548..9e27dffbb3c3 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.7.0 github.com/quic-go/quic-go v0.45.1 + github.com/refraction-networking/uquic v0.0.5 github.com/refraction-networking/utls v1.6.7 github.com/sagernet/sing v0.4.1 github.com/sagernet/sing-shadowsocks v0.2.7 @@ -39,8 +40,11 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/francoispqt/gojay v1.2.13 // indirect + github.com/gaukas/clienthellod v0.4.2 // indirect + github.com/gaukas/godicttls v0.0.4 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/btree v1.1.2 // indirect + github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect github.com/klauspost/compress v1.17.8 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect diff --git a/go.sum b/go.sum index 15137ad3c8e7..9594abfb5382 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,10 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gaukas/clienthellod v0.4.2 h1:LPJ+LSeqt99pqeCV4C0cllk+pyWmERisP7w6qWr7eqE= +github.com/gaukas/clienthellod v0.4.2/go.mod h1:M57+dsu0ZScvmdnNxaxsDPM46WhSEdPYAOdNgfL7IKA= +github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= +github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= @@ -57,6 +61,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g= @@ -114,6 +120,8 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjCA= github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI= +github.com/refraction-networking/uquic v0.0.5 h1:Ldk4nY6KaxI0PtMDGelzesdmZSuMywY9DOmqKsH7AV8= +github.com/refraction-networking/uquic v0.0.5/go.mod h1:ts5LSEq8Cn34V5CyeJqGkRTwBGI8Ij1ckJQ8K4YEUig= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= @@ -187,6 +195,8 @@ golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQ golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -247,6 +257,7 @@ golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= diff --git a/transport/internet/splithttp/dialer.go b/transport/internet/splithttp/dialer.go index 9f98da3d96fa..75c441942eda 100644 --- a/transport/internet/splithttp/dialer.go +++ b/transport/internet/splithttp/dialer.go @@ -7,11 +7,14 @@ import ( "net/http" "net/url" "strconv" + "strings" "sync" "time" - "github.com/quic-go/quic-go" - "github.com/quic-go/quic-go/http3" + "github.com/refraction-networking/uquic" + "github.com/refraction-networking/uquic/http3" + utls "github.com/refraction-networking/utls" + "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/errors" @@ -93,10 +96,17 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in KeepAlivePeriod: 3 * time.Second, Allow0RTT: true, } + utlsConfig := &utls.Config{ + RootCAs: gotlsConfig.RootCAs, + ServerName: gotlsConfig.ServerName, + InsecureSkipVerify: gotlsConfig.InsecureSkipVerify, + VerifyPeerCertificate: gotlsConfig.VerifyPeerCertificate, + KeyLogWriter: gotlsConfig.KeyLogWriter, + } roundTripper := &http3.RoundTripper{ - TLSClientConfig: gotlsConfig, - QUICConfig: quicConfig, - Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { + TLSClientConfig: utlsConfig, + QuicConfig: quicConfig, + Dial: func(ctx context.Context, addr string, tlsCfg *utls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings) if err != nil { return nil, err @@ -108,8 +118,42 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in return quic.DialEarly(ctx, conn.(*internet.PacketConnWrapper).Conn.(*net.UDPConn), udpAddr, tlsCfg, cfg) }, } - downloadTransport = roundTripper - uploadTransport = roundTripper + + if(gotlsConfig == nil){ + downloadTransport = roundTripper + uploadTransport = roundTripper + } else if tlsConfig.GetFingerprint() == "" { + downloadTransport = roundTripper + uploadTransport = roundTripper + } else { + var quicSpec quic.QUICSpec + var err error + + // fingerprints available for QUIC are different from those of TCP TLS, so it has been implemented this way for now + // so that users who previously used http1.1 or h2 may not have to adjust their configurations as much. + // it should be changed in the future. (When you do this there will be many users crying that her client stopped working) + if(strings.Contains(strings.ToLower(tlsConfig.GetFingerprint()),"chrome")){ + quicSpec, err = quic.QUICID2Spec(quic.QUICChrome_115) + } else if strings.Contains(strings.ToLower(tlsConfig.GetFingerprint()),"firefox") { + quicSpec, err = quic.QUICID2Spec(quic.QUICFirefox_116) + } else { + errors.LogError(ctx,"unknown fingerprint: ",tlsConfig.GetFingerprint()) + return nil + } + + if err != nil { + errors.LogError(ctx,tlsConfig.GetFingerprint()) + return nil + } + + uRoundTripper := http3.GetURoundTripper( + roundTripper, + &quicSpec, + nil, + ) + downloadTransport = uRoundTripper + uploadTransport = uRoundTripper + } } else if isH2 { downloadTransport = &http2.Transport{ DialTLSContext: func(ctxInner context.Context, network string, addr string, cfg *gotls.Config) (net.Conn, error) { From 1bcb650afebdc126b36f38292b5c4cca9e091bff Mon Sep 17 00:00:00 2001 From: YUNRU Date: Thu, 18 Jul 2024 03:37:18 +0800 Subject: [PATCH 2/7] Replace quic-go with uQuic --- app/dns/nameserver_quic.go | 4 ++-- common/protocol/quic/sniff.go | 2 +- go.mod | 1 - go.sum | 2 -- transport/internet/quic/conn.go | 2 +- transport/internet/quic/dialer.go | 8 ++++---- transport/internet/quic/hub.go | 8 ++++---- transport/internet/quic/qlogWriter.go | 2 +- transport/internet/tls/tls.go | 4 ++-- 9 files changed, 15 insertions(+), 18 deletions(-) diff --git a/app/dns/nameserver_quic.go b/app/dns/nameserver_quic.go index 2d56f43e69cb..f256ee957caf 100644 --- a/app/dns/nameserver_quic.go +++ b/app/dns/nameserver_quic.go @@ -9,7 +9,7 @@ import ( "sync/atomic" "time" - "github.com/quic-go/quic-go" + "github.com/refraction-networking/uquic" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/errors" @@ -400,7 +400,7 @@ func (s *QUICNameServer) openConnection() (quic.Connection, error) { HandshakeIdleTimeout: handshakeTimeout, } tlsConfig.ServerName = s.destination.Address.String() - conn, err := quic.DialAddr(context.Background(), s.destination.NetAddr(), tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ)), quicConfig) + conn, err := quic.DialAddr(context.Background(), s.destination.NetAddr(), tls.ToUTLSConfig(tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ))), quicConfig) log.Record(&log.AccessMessage{ From: "DNS", To: s.destination, diff --git a/common/protocol/quic/sniff.go b/common/protocol/quic/sniff.go index bf4614648420..356f2de2c40b 100644 --- a/common/protocol/quic/sniff.go +++ b/common/protocol/quic/sniff.go @@ -7,7 +7,7 @@ import ( "encoding/binary" "io" - "github.com/quic-go/quic-go/quicvarint" + "github.com/refraction-networking/uquic/quicvarint" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/bytespool" diff --git a/go.mod b/go.mod index 9e27dffbb3c3..a5d46fba3020 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/miekg/dns v1.1.61 github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.7.0 - github.com/quic-go/quic-go v0.45.1 github.com/refraction-networking/uquic v0.0.5 github.com/refraction-networking/utls v1.6.7 github.com/sagernet/sing v0.4.1 diff --git a/go.sum b/go.sum index 9594abfb5382..d730256aaaa5 100644 --- a/go.sum +++ b/go.sum @@ -118,8 +118,6 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjCA= -github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI= github.com/refraction-networking/uquic v0.0.5 h1:Ldk4nY6KaxI0PtMDGelzesdmZSuMywY9DOmqKsH7AV8= github.com/refraction-networking/uquic v0.0.5/go.mod h1:ts5LSEq8Cn34V5CyeJqGkRTwBGI8Ij1ckJQ8K4YEUig= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= diff --git a/transport/internet/quic/conn.go b/transport/internet/quic/conn.go index 11bee7c543a9..1b3da91e29b0 100644 --- a/transport/internet/quic/conn.go +++ b/transport/internet/quic/conn.go @@ -7,7 +7,7 @@ import ( "syscall" "time" - "github.com/quic-go/quic-go" + "github.com/refraction-networking/uquic" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/net" diff --git a/transport/internet/quic/dialer.go b/transport/internet/quic/dialer.go index df73e169d4fc..516f03aaa8cd 100644 --- a/transport/internet/quic/dialer.go +++ b/transport/internet/quic/dialer.go @@ -5,9 +5,9 @@ import ( "sync" "time" - "github.com/quic-go/quic-go" - "github.com/quic-go/quic-go/logging" - "github.com/quic-go/quic-go/qlog" + "github.com/refraction-networking/uquic" + "github.com/refraction-networking/uquic/logging" + "github.com/refraction-networking/uquic/qlog" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/net" @@ -169,7 +169,7 @@ func (s *clientConnections) openConnection(ctx context.Context, destAddr net.Add ConnectionIDLength: 12, Conn: sysConn, } - conn, err := tr.Dial(context.Background(), destAddr, tlsConfig.GetTLSConfig(tls.WithDestination(dest)), quicConfig) + conn, err := tr.Dial(context.Background(), destAddr, tls.ToUTLSConfig(tlsConfig.GetTLSConfig(tls.WithDestination(dest))), quicConfig) if err != nil { sysConn.Close() return nil, err diff --git a/transport/internet/quic/hub.go b/transport/internet/quic/hub.go index de8919fdb1e8..1c2b30c3cd42 100644 --- a/transport/internet/quic/hub.go +++ b/transport/internet/quic/hub.go @@ -4,9 +4,9 @@ import ( "context" "time" - "github.com/quic-go/quic-go" - "github.com/quic-go/quic-go/logging" - "github.com/quic-go/quic-go/qlog" + "github.com/refraction-networking/uquic" + "github.com/refraction-networking/uquic/logging" + "github.com/refraction-networking/uquic/qlog" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/net" @@ -123,7 +123,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti ConnectionIDLength: 12, Conn: conn, } - qListener, err := tr.Listen(tlsConfig.GetTLSConfig(), quicConfig) + qListener, err := tr.Listen(tls.ToUTLSConfig(tlsConfig.GetTLSConfig()), quicConfig) if err != nil { conn.Close() return nil, err diff --git a/transport/internet/quic/qlogWriter.go b/transport/internet/quic/qlogWriter.go index 54284d29cea6..20c9f811f243 100644 --- a/transport/internet/quic/qlogWriter.go +++ b/transport/internet/quic/qlogWriter.go @@ -1,6 +1,6 @@ package quic -import "github.com/quic-go/quic-go" +import "github.com/refraction-networking/uquic" type QlogWriter struct { connID quic.ConnectionID diff --git a/transport/internet/tls/tls.go b/transport/internet/tls/tls.go index 25889cb12adb..7d19fd61ee62 100644 --- a/transport/internet/tls/tls.go +++ b/transport/internet/tls/tls.go @@ -131,11 +131,11 @@ func (c *UConn) NegotiatedProtocol() string { } func UClient(c net.Conn, config *tls.Config, fingerprint *utls.ClientHelloID) net.Conn { - utlsConn := utls.UClient(c, copyConfig(config), *fingerprint) + utlsConn := utls.UClient(c, ToUTLSConfig(config), *fingerprint) return &UConn{UConn: utlsConn} } -func copyConfig(c *tls.Config) *utls.Config { +func ToUTLSConfig(c *tls.Config) *utls.Config { return &utls.Config{ RootCAs: c.RootCAs, ServerName: c.ServerName, From be8c04c3541be3b09b57df92ec310dbf5cf8970b Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:01:21 -0500 Subject: [PATCH 3/7] bump uquic --- go.mod | 4 +++- go.sum | 13 ++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index a5d46fba3020..4e15667b4921 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,8 @@ require ( github.com/miekg/dns v1.1.61 github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.7.0 - github.com/refraction-networking/uquic v0.0.5 + github.com/quic-go/quic-go v0.39.0 + github.com/refraction-networking/uquic v0.0.6 github.com/refraction-networking/utls v1.6.7 github.com/sagernet/sing v0.4.1 github.com/sagernet/sing-shadowsocks v0.2.7 @@ -50,6 +51,7 @@ require ( github.com/onsi/ginkgo/v2 v2.19.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-20 v0.3.4 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/vishvananda/netns v0.0.4 // indirect go.uber.org/mock v0.4.0 // indirect diff --git a/go.sum b/go.sum index d730256aaaa5..b17040485d39 100644 --- a/go.sum +++ b/go.sum @@ -84,9 +84,11 @@ github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0N github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -118,8 +120,12 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/refraction-networking/uquic v0.0.5 h1:Ldk4nY6KaxI0PtMDGelzesdmZSuMywY9DOmqKsH7AV8= -github.com/refraction-networking/uquic v0.0.5/go.mod h1:ts5LSEq8Cn34V5CyeJqGkRTwBGI8Ij1ckJQ8K4YEUig= +github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= +github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3So= +github.com/quic-go/quic-go v0.39.0/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q= +github.com/refraction-networking/uquic v0.0.6 h1:9ol1oOaOpHDeeDlBY7u228jK+T5oic35QrFimHVaCMM= +github.com/refraction-networking/uquic v0.0.6/go.mod h1:TFgTmV/yqVCMEXVwP7z7PMAhzye02rFHLV6cRAg59jc= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= @@ -288,8 +294,9 @@ google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From a1d469f04aa7c66238af2254b816ff2c2524178c Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:01:33 -0500 Subject: [PATCH 4/7] formatting --- transport/internet/splithttp/dialer.go | 10 +++++----- transport/internet/splithttp/hub.go | 5 ++--- transport/internet/splithttp/splithttp_test.go | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/transport/internet/splithttp/dialer.go b/transport/internet/splithttp/dialer.go index dafe81a07056..b547fd32ed1b 100644 --- a/transport/internet/splithttp/dialer.go +++ b/transport/internet/splithttp/dialer.go @@ -140,7 +140,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in }, } - if(gotlsConfig == nil){ + if gotlsConfig == nil { downloadTransport = roundTripper uploadTransport = roundTripper } else if tlsConfig.GetFingerprint() == "" { @@ -153,17 +153,17 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in // fingerprints available for QUIC are different from those of TCP TLS, so it has been implemented this way for now // so that users who previously used http1.1 or h2 may not have to adjust their configurations as much. // it should be changed in the future. (When you do this there will be many users crying that her client stopped working) - if(strings.Contains(strings.ToLower(tlsConfig.GetFingerprint()),"chrome")){ + if strings.Contains(strings.ToLower(tlsConfig.GetFingerprint()), "chrome") { quicSpec, err = quic.QUICID2Spec(quic.QUICChrome_115) - } else if strings.Contains(strings.ToLower(tlsConfig.GetFingerprint()),"firefox") { + } else if strings.Contains(strings.ToLower(tlsConfig.GetFingerprint()), "firefox") { quicSpec, err = quic.QUICID2Spec(quic.QUICFirefox_116) } else { - errors.LogError(ctx,"unknown fingerprint: ",tlsConfig.GetFingerprint()) + errors.LogError(ctx, "unknown fingerprint: ", tlsConfig.GetFingerprint()) return nil } if err != nil { - errors.LogError(ctx,tlsConfig.GetFingerprint()) + errors.LogError(ctx, tlsConfig.GetFingerprint()) return nil } diff --git a/transport/internet/splithttp/hub.go b/transport/internet/splithttp/hub.go index 1ce8da6b0966..ff922a765e81 100644 --- a/transport/internet/splithttp/hub.go +++ b/transport/internet/splithttp/hub.go @@ -269,7 +269,6 @@ func ListenSH(ctx context.Context, address net.Address, port net.Port, streamSet tlsConfig := getTLSConfig(streamSettings) l.isH3 = len(tlsConfig.NextProtos) == 1 && tlsConfig.NextProtos[0] == "h3" - if port == net.Port(0) { // unix listener, err = internet.ListenSystem(ctx, &net.UnixAddr{ Name: address.Domain(), @@ -285,9 +284,9 @@ func ListenSH(ctx context.Context, address net.Address, port net.Port, streamSet Port: int(port), }, streamSettings.SocketSettings) if err != nil { - return nil, errors.New("failed to listen UDP(for SH3) on ", address, ":", port).Base(err) + return nil, errors.New("failed to listen UDP(for SH3) on ", address, ":", port).Base(err) } - h3listener, err := quic.ListenEarly(Conn,tlsConfig, nil) + h3listener, err := quic.ListenEarly(Conn, tlsConfig, nil) if err != nil { return nil, errors.New("failed to listen QUIC(for SH3) on ", address, ":", port).Base(err) } diff --git a/transport/internet/splithttp/splithttp_test.go b/transport/internet/splithttp/splithttp_test.go index 5f59a738caa2..2061c32d6791 100644 --- a/transport/internet/splithttp/splithttp_test.go +++ b/transport/internet/splithttp/splithttp_test.go @@ -243,4 +243,4 @@ func Test_listenSHAndDial_QUIC(t *testing.T) { if !end.Before(start.Add(time.Second * 5)) { t.Error("end: ", end, " start: ", start) } -} \ No newline at end of file +} From f7faecbd370714e4c60dadb29a8f23368a304e32 Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:22:29 -0500 Subject: [PATCH 5/7] remove quic-go entirely --- go.mod | 2 -- go.sum | 4 ---- transport/internet/splithttp/hub.go | 6 +++--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 4e15667b4921..33e69062628b 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/miekg/dns v1.1.61 github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.7.0 - github.com/quic-go/quic-go v0.39.0 github.com/refraction-networking/uquic v0.0.6 github.com/refraction-networking/utls v1.6.7 github.com/sagernet/sing v0.4.1 @@ -51,7 +50,6 @@ require ( github.com/onsi/ginkgo/v2 v2.19.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.4 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/vishvananda/netns v0.0.4 // indirect go.uber.org/mock v0.4.0 // indirect diff --git a/go.sum b/go.sum index b17040485d39..ea10b46ce1dd 100644 --- a/go.sum +++ b/go.sum @@ -120,10 +120,6 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= -github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3So= -github.com/quic-go/quic-go v0.39.0/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q= github.com/refraction-networking/uquic v0.0.6 h1:9ol1oOaOpHDeeDlBY7u228jK+T5oic35QrFimHVaCMM= github.com/refraction-networking/uquic v0.0.6/go.mod h1:TFgTmV/yqVCMEXVwP7z7PMAhzye02rFHLV6cRAg59jc= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= diff --git a/transport/internet/splithttp/hub.go b/transport/internet/splithttp/hub.go index ff922a765e81..9fea6dae18dd 100644 --- a/transport/internet/splithttp/hub.go +++ b/transport/internet/splithttp/hub.go @@ -11,8 +11,8 @@ import ( "sync" "time" - "github.com/quic-go/quic-go" - "github.com/quic-go/quic-go/http3" + "github.com/refraction-networking/uquic" + "github.com/refraction-networking/uquic/http3" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/net" @@ -286,7 +286,7 @@ func ListenSH(ctx context.Context, address net.Address, port net.Port, streamSet if err != nil { return nil, errors.New("failed to listen UDP(for SH3) on ", address, ":", port).Base(err) } - h3listener, err := quic.ListenEarly(Conn, tlsConfig, nil) + h3listener, err := quic.ListenEarly(Conn, v2tls.ToUTLSConfig(tlsConfig), nil) if err != nil { return nil, errors.New("failed to listen QUIC(for SH3) on ", address, ":", port).Base(err) } From dd876d59eb7e10a59b7d1d4e59c09a78a0f771b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A3=8E=E6=89=87=E6=BB=91=E7=BF=94=E7=BF=BC?= Date: Sat, 20 Jul 2024 04:00:47 +0800 Subject: [PATCH 6/7] Try to fix alpn err --- transport/internet/tls/tls.go | 1 + 1 file changed, 1 insertion(+) diff --git a/transport/internet/tls/tls.go b/transport/internet/tls/tls.go index 7d19fd61ee62..07b86343a6e9 100644 --- a/transport/internet/tls/tls.go +++ b/transport/internet/tls/tls.go @@ -142,6 +142,7 @@ func ToUTLSConfig(c *tls.Config) *utls.Config { InsecureSkipVerify: c.InsecureSkipVerify, VerifyPeerCertificate: c.VerifyPeerCertificate, KeyLogWriter: c.KeyLogWriter, + NextProtos: c.NextProtos, } } From 88a0beb6495a06938e5e50974fe5a516ad870c61 Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:04:21 -0500 Subject: [PATCH 7/7] make quic and splithttp test exactly the same --- transport/internet/quic/quic_test.go | 28 ++++--------- .../internet/splithttp/splithttp_test.go | 41 ++++++++++++++++++- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/transport/internet/quic/quic_test.go b/transport/internet/quic/quic_test.go index ab07105895a0..402926ee8558 100644 --- a/transport/internet/quic/quic_test.go +++ b/transport/internet/quic/quic_test.go @@ -24,20 +24,18 @@ import ( func TestQuicConnection(t *testing.T) { port := udp.PickPort() - listener, err := quic.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{ + streamSettings := &internet.MemoryStreamConfig{ ProtocolName: "quic", ProtocolSettings: &quic.Config{}, SecurityType: "tls", SecuritySettings: &tls.Config{ - Certificate: []*tls.Certificate{ - tls.ParseCertificate( - cert.MustGenerate(nil, - cert.DNSNames("www.example.com"), - ), - ), - }, + AllowInsecure: true, + Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil, cert.CommonName("localhost")))}, + NextProtocol: []string{"h3"}, }, - }, func(conn stat.Connection) { + } + + listener, err := quic.Listen(context.Background(), net.LocalHostIP, port, streamSettings, func(conn stat.Connection) { go func() { defer conn.Close() @@ -54,21 +52,11 @@ func TestQuicConnection(t *testing.T) { }() }) common.Must(err) - defer listener.Close() time.Sleep(time.Second) - dctx := context.Background() - conn, err := quic.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{ - ProtocolName: "quic", - ProtocolSettings: &quic.Config{}, - SecurityType: "tls", - SecuritySettings: &tls.Config{ - ServerName: "www.example.com", - AllowInsecure: true, - }, - }) + conn, err := quic.Dial(context.Background(), net.UDPDestination(net.DomainAddress("localhost"), port), streamSettings) common.Must(err) defer conn.Close() diff --git a/transport/internet/splithttp/splithttp_test.go b/transport/internet/splithttp/splithttp_test.go index 2061c32d6791..a571c6ff2cfc 100644 --- a/transport/internet/splithttp/splithttp_test.go +++ b/transport/internet/splithttp/splithttp_test.go @@ -2,6 +2,7 @@ package splithttp_test import ( "context" + "crypto/rand" gotls "crypto/tls" "fmt" gonet "net" @@ -10,7 +11,9 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol/tls/cert" "github.com/xtls/xray-core/testing/servers/tcp" @@ -229,15 +232,49 @@ func Test_listenSHAndDial_QUIC(t *testing.T) { } listen, err := ListenSH(context.Background(), net.LocalHostIP, listenPort, streamSettings, func(conn stat.Connection) { go func() { - _ = conn.Close() + defer conn.Close() + + b := buf.New() + defer b.Release() + + for { + b.Clear() + if _, err := b.ReadFrom(conn); err != nil { + return + } + common.Must2(conn.Write(b.Bytes())) + } }() }) common.Must(err) defer listen.Close() + time.Sleep(time.Second) + conn, err := Dial(context.Background(), net.UDPDestination(net.DomainAddress("localhost"), listenPort), streamSettings) common.Must(err) - _ = conn.Close() + defer conn.Close() + + const N = 1024 + b1 := make([]byte, N) + common.Must2(rand.Read(b1)) + b2 := buf.New() + + common.Must2(conn.Write(b1)) + + b2.Clear() + common.Must2(b2.ReadFullFrom(conn, N)) + if r := cmp.Diff(b2.Bytes(), b1); r != "" { + t.Error(r) + } + + common.Must2(conn.Write(b1)) + + b2.Clear() + common.Must2(b2.ReadFullFrom(conn, N)) + if r := cmp.Diff(b2.Bytes(), b1); r != "" { + t.Error(r) + } end := time.Now() if !end.Before(start.Add(time.Second * 5)) {