From 8883fd2caccb0c1ead5fde0d220fd1df66f8f404 Mon Sep 17 00:00:00 2001 From: gospider <2216403312@qq.com> Date: Tue, 10 Jun 2025 14:11:15 +0800 Subject: [PATCH] sync --- compressConn.go | 121 ++++++++++++++++++++++++++++++++++-------------- conn.go | 37 +++++++++++++++ dial.go | 27 +++++++++-- go.mod | 26 +++++------ go.sum | 50 ++++++++++---------- http.go | 5 +- roundTripper.go | 62 +++++++++++++++++++++---- rw.go | 4 -- socks5.go | 6 +++ tools.go | 4 ++ 10 files changed, 251 insertions(+), 91 deletions(-) diff --git a/compressConn.go b/compressConn.go index 82968aa..23db399 100644 --- a/compressConn.go +++ b/compressConn.go @@ -1,6 +1,7 @@ package requests import ( + "compress/flate" "errors" "io" "net" @@ -8,7 +9,6 @@ import ( "time" "github.com/klauspost/compress/zstd" - "github.com/mholt/archives" ) type CompressionConn struct { @@ -17,17 +17,97 @@ type CompressionConn struct { r io.ReadCloser f interface{ Flush() error } } +type Compression interface { + OpenReader(r io.Reader) (io.ReadCloser, error) + OpenWriter(w io.Writer) (io.WriteCloser, error) +} +type compression struct { + openReader func(r io.Reader) (io.ReadCloser, error) + openWriter func(w io.Writer) (io.WriteCloser, error) +} -func NewCompressionConn(decode string, conn net.Conn) (net.Conn, error) { - var r io.ReadCloser - var w io.WriteCloser - var err error +func (obj compression) OpenReader(r io.Reader) (io.ReadCloser, error) { + return obj.openReader(r) +} +func (obj compression) OpenWriter(w io.Writer) (io.WriteCloser, error) { + return obj.openWriter(w) +} + +type CompressionLevel int + +const ( + CompressionLevelFast CompressionLevel = 1 + CompressionLevelBest CompressionLevel = 2 +) + +func NewCompression(decode string, leval CompressionLevel) (Compression, error) { + var arch Compression switch strings.ToLower(decode) { case "zstd": - r, w, err = newZstdConn(conn) + options := []zstd.EOption{} + options2 := []zstd.DOption{} + switch leval { + case CompressionLevelFast: + options = append(options, zstd.WithEncoderLevel(zstd.SpeedFastest), zstd.WithZeroFrames(true), zstd.WithLowerEncoderMem(true)) + options2 = append(options2, zstd.WithDecoderLowmem(true)) + case CompressionLevelBest: + options = append(options, zstd.WithEncoderLevel(zstd.SpeedBetterCompression)) + default: + options = append(options, zstd.WithEncoderLevel(zstd.SpeedDefault), zstd.WithZeroFrames(true), zstd.WithLowerEncoderMem(true)) + options2 = append(options2, zstd.WithDecoderLowmem(true)) + } + arch = compression{ + openReader: func(r io.Reader) (io.ReadCloser, error) { + decoder, err := zstd.NewReader(r, options2...) + if err != nil { + return nil, err + } + return decoder.IOReadCloser(), nil + }, + openWriter: func(w io.Writer) (io.WriteCloser, error) { + encoder, err := zstd.NewWriter(w, options...) + if err != nil { + return nil, err + } + return encoder, nil + }, + } + case "flate": + arch = compression{ + openReader: func(r io.Reader) (io.ReadCloser, error) { + buf := make([]byte, 1) + n, err := r.Read(buf) + if err != nil { + return nil, err + } + if n != 1 || buf[0] != 92 { + return nil, errors.New("invalid response") + } + return flate.NewReader(r), nil + }, + openWriter: func(w io.Writer) (io.WriteCloser, error) { + n, err := w.Write([]byte{92}) + if err != nil { + return nil, err + } + if n != 1 { + return nil, errors.New("invalid response") + } + return flate.NewWriter(w, flate.BestCompression) + }, + } default: return nil, errors.New("unsupported compression type") } + return arch, nil +} + +func NewCompressionConn(conn net.Conn, arch Compression) (net.Conn, error) { + w, err := arch.OpenWriter(conn) + if err != nil { + return nil, err + } + r, err := arch.OpenReader(conn) if err != nil { return nil, err } @@ -38,35 +118,6 @@ func NewCompressionConn(decode string, conn net.Conn) (net.Conn, error) { return ccon, nil } -func newZstdConn(conn net.Conn) (io.ReadCloser, io.WriteCloser, error) { - r, err := archives.Zstd{ - EncoderOptions: []zstd.EOption{ - zstd.WithEncoderLevel(zstd.SpeedFastest), - zstd.WithWindowSize(zstd.MinWindowSize), // 1MB 窗口,减少内存 - zstd.WithEncoderConcurrency(1), // 单线程,减少内存 - }, - DecoderOptions: []zstd.DOption{ - zstd.WithDecodeBuffersBelow(zstd.MinWindowSize), - }, - }.OpenReader(conn) - if err != nil { - return nil, nil, err - } - w, err := archives.Zstd{ - EncoderOptions: []zstd.EOption{ - zstd.WithEncoderLevel(zstd.SpeedFastest), - zstd.WithWindowSize(zstd.MinWindowSize), // 1MB 窗口,减少内存 - zstd.WithEncoderConcurrency(1), // 单线程,减少内存 - }, - DecoderOptions: []zstd.DOption{ - zstd.WithDecodeBuffersBelow(zstd.MinWindowSize), - }, - }.OpenWriter(conn) - if err != nil { - return nil, nil, err - } - return r, w, nil -} func (obj *CompressionConn) Read(b []byte) (n int, err error) { return obj.r.Read(b) } diff --git a/conn.go b/conn.go index fa80cc2..b33de6a 100644 --- a/conn.go +++ b/conn.go @@ -200,3 +200,40 @@ func (obj *connPool) close(err error) { obj.connPools.del(obj.connKey) obj.forceCnl(tools.WrapError(err, "connPool close")) } + +func newSSHConn(sshCon net.Conn, rawCon net.Conn) *sshConn { + return &sshConn{sshCon: sshCon, rawCon: rawCon} +} + +type sshConn struct { + sshCon net.Conn + rawCon net.Conn +} + +func (obj *sshConn) Read(b []byte) (n int, err error) { + return obj.sshCon.Read(b) +} + +func (obj *sshConn) Write(b []byte) (n int, err error) { + return obj.sshCon.Write(b) +} + +func (obj *sshConn) Close() error { + return obj.sshCon.Close() +} +func (obj *sshConn) LocalAddr() net.Addr { + return obj.sshCon.LocalAddr() +} +func (obj *sshConn) RemoteAddr() net.Addr { + return obj.sshCon.RemoteAddr() +} +func (obj *sshConn) SetDeadline(deadline time.Time) error { + return obj.rawCon.SetDeadline(deadline) +} +func (obj *sshConn) SetReadDeadline(deadline time.Time) error { + return obj.rawCon.SetReadDeadline(deadline) +} + +func (obj *sshConn) SetWriteDeadline(deadline time.Time) error { + return obj.rawCon.SetWriteDeadline(deadline) +} diff --git a/dial.go b/dial.go index 1a69c88..e1c5e3d 100644 --- a/dial.go +++ b/dial.go @@ -17,6 +17,7 @@ import ( "github.com/gospider007/ja3" "github.com/gospider007/tools" utls "github.com/refraction-networking/utls" + "golang.org/x/crypto/ssh" ) type msgClient struct { @@ -135,9 +136,6 @@ func (obj *Dialer) dialContext(ctx *Response, network string, addr Address, isPr }) } } - if err == nil && addr.Compression != "" { - return NewCompressionConn(addr.Compression, con) - } return con, err } func (obj *Dialer) DialContext(ctx *Response, network string, addr Address) (net.Conn, error) { @@ -177,6 +175,26 @@ func (obj *Dialer) DialProxyContext(ctx *Response, network string, proxyTlsConfi func (obj *Dialer) dialProxyContext(ctx *Response, network string, proxyUrl Address) (net.Conn, error) { return obj.ProxyDialContext(ctx, network, proxyUrl) } + +func (obj *Dialer) verifySSH(ctx *Response, conn net.Conn, proxyAddress Address, remoteAddress Address) (net.Conn, error) { + if proxyAddress.User == "" || proxyAddress.Password == "" { + return conn, errors.New("ssh proxy user or password is nil") + } + config := &ssh.ClientConfig{ + User: proxyAddress.User, + Auth: []ssh.AuthMethod{ssh.Password(proxyAddress.Password)}, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + c, chans, reqs, err := ssh.NewClientConn(conn, proxyAddress.String(), config) + if err != nil { + return conn, err + } + sshC, err := ssh.NewClient(c, chans, reqs).DialContext(ctx.Context(), "tcp", remoteAddress.String()) + if err != nil { + return conn, err + } + return newSSHConn(sshC, conn), nil +} func (obj *Dialer) verifyProxyToRemote(ctx *Response, conn net.Conn, proxyTlsConfig *tls.Config, proxyAddress Address, remoteAddress Address, isLast bool, forceHttp1 bool) (net.PacketConn, net.Conn, error) { var err error var packCon net.PacketConn @@ -206,6 +224,9 @@ func (obj *Dialer) verifyProxyToRemote(ctx *Response, conn net.Conn, proxyTlsCon Msg: remoteAddress.String(), }) } + case "ssh": + conn, err = obj.verifySSH(ctx, conn, proxyAddress, remoteAddress) + // log.Print("verify ssh", remoteAddress.String(), err) case "socks5": if isLast && ctx.option.ForceHttp3 { packCon, err = obj.verifyUDPSocks5(ctx, conn, proxyAddress, remoteAddress) diff --git a/go.mod b/go.mod index 3873609..e1da772 100644 --- a/go.mod +++ b/go.mod @@ -6,20 +6,20 @@ require ( github.com/gospider007/bar v0.0.0-20250217074946-47896d8de2ba github.com/gospider007/bs4 v0.0.0-20250413121342-fed910fb00c9 github.com/gospider007/gson v0.0.0-20250530002642-aee7c1b761df - github.com/gospider007/gtls v0.0.0-20250427082859-097a9e35c601 + github.com/gospider007/gtls v0.0.0-20250610060422-446e017b9858 github.com/gospider007/http2 v0.0.0-20250427082905-4aed0707e580 github.com/gospider007/http3 v0.0.0-20250416085920-b642f3f91f47 github.com/gospider007/ja3 v0.0.0-20250427082442-f7dc5fb959e6 github.com/gospider007/re v0.0.0-20250217075352-bcb79f285d6c - github.com/gospider007/tools v0.0.0-20250529114105-be4d4dbf36a2 + github.com/gospider007/tools v0.0.0-20250610060552-2e45eaa25022 github.com/gospider007/websocket v0.0.0-20250429035144-b1cf6819063a github.com/klauspost/compress v1.18.0 - github.com/mholt/archives v0.1.2 github.com/quic-go/quic-go v0.52.0 github.com/refraction-networking/uquic v0.0.6 github.com/refraction-networking/utls v1.7.3 github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301 - golang.org/x/net v0.40.0 + golang.org/x/crypto v0.39.0 + golang.org/x/net v0.41.0 gopkg.in/errgo.v2 v2.1.0 ) @@ -43,7 +43,7 @@ require ( github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/ws v1.4.0 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20250602020802-c6617b811d0e // indirect + github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a // indirect github.com/gospider007/blog v0.0.0-20250302134054-8afc12c2a9a7 // indirect github.com/gospider007/kinds v0.0.0-20250217075226-10f199f7215d // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect @@ -53,6 +53,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/libdns/libdns v1.1.0 // indirect github.com/mholt/acmez/v3 v3.1.2 // indirect + github.com/mholt/archives v0.1.2 // indirect github.com/miekg/dns v1.1.66 // indirect github.com/minio/minlz v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -72,21 +73,20 @@ require ( github.com/txthinking/runnergroup v0.0.0-20250224021307-5864ffeb65ae // indirect github.com/ulikunitz/xz v0.5.12 // indirect github.com/zeebo/blake3 v0.2.4 // indirect - go.mongodb.org/mongo-driver v1.17.3 // indirect + go.mongodb.org/mongo-driver v1.17.4 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/mock v0.5.2 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/crypto v0.38.0 // indirect - golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b // indirect - golang.org/x/image v0.27.0 // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/sync v0.14.0 // indirect + golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 // indirect + golang.org/x/image v0.28.0 // indirect + golang.org/x/mod v0.25.0 // indirect + golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.25.0 // indirect + golang.org/x/text v0.26.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/tools v0.34.0 // indirect google.golang.org/protobuf v1.36.6 // indirect ) diff --git a/go.sum b/go.sum index fdbb04d..cd6af07 100644 --- a/go.sum +++ b/go.sum @@ -97,8 +97,8 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20250602020802-c6617b811d0e h1:FJta/0WsADCe1r9vQjdHbd3KuiLPu7Y9WlyLGwMUNyE= -github.com/google/pprof v0.0.0-20250602020802-c6617b811d0e/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= +github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a h1://KbezygeMJZCSHH+HgUZiTeSoiuFspbMg1ge+eFj18= +github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -110,8 +110,8 @@ github.com/gospider007/bs4 v0.0.0-20250413121342-fed910fb00c9 h1:V/Fuzox1GNZzlZC github.com/gospider007/bs4 v0.0.0-20250413121342-fed910fb00c9/go.mod h1:KBnaNWpVupRQbPZ6jz2jhX/hnRK1w30RKJvl3Micjws= github.com/gospider007/gson v0.0.0-20250530002642-aee7c1b761df h1:Xi1Sm1caw39tXUVZAuVAVSdJ9x7h0Y1bPOw3sxxkzsM= github.com/gospider007/gson v0.0.0-20250530002642-aee7c1b761df/go.mod h1:+O/+tzjrqz67RehAyJaRApESHo1Z9fuxBeQmQ8GMELw= -github.com/gospider007/gtls v0.0.0-20250427082859-097a9e35c601 h1:0r67F8bARNcUwMpSVCgp5u92sP01kWgZLRliRFKmgMM= -github.com/gospider007/gtls v0.0.0-20250427082859-097a9e35c601/go.mod h1:UzfvBwe5Jtz1nKzlGSH4q8VP/9XfcsmMFDahR3PgCkM= +github.com/gospider007/gtls v0.0.0-20250610060422-446e017b9858 h1:Tb+T5YfysjR7Mp22AgrJhMPF28KBgjWkbKj2zi8AyBU= +github.com/gospider007/gtls v0.0.0-20250610060422-446e017b9858/go.mod h1:SxhMpxq4EYHlUre2EdQ4dKKGZyvj7+1PYZ2LQ9RO0y4= github.com/gospider007/http2 v0.0.0-20250427082905-4aed0707e580 h1:JLZeCin6giqOV3sAy7BGqFkc+qHvO389O/aTT5JJc1k= github.com/gospider007/http2 v0.0.0-20250427082905-4aed0707e580/go.mod h1:WH7RqG9ecX15uAhzZDr5cbTaTPZST3ST0X4okNDSR5I= github.com/gospider007/http3 v0.0.0-20250416085920-b642f3f91f47 h1:dpV6hkUeMbZrCZSaR99u6TNXry9M3FSga+9CmjZ5Zmo= @@ -122,8 +122,8 @@ github.com/gospider007/kinds v0.0.0-20250217075226-10f199f7215d h1:+Fih572EdNmYC github.com/gospider007/kinds v0.0.0-20250217075226-10f199f7215d/go.mod h1:3u6J+nbdWhCNJGiQjq/hKSukn2k6ebjd98rd2+fzKNo= github.com/gospider007/re v0.0.0-20250217075352-bcb79f285d6c h1:8/Cf+c2680tkWJ+ueZ9RLLK5R5R8nhE8pNBUPHjkvkM= github.com/gospider007/re v0.0.0-20250217075352-bcb79f285d6c/go.mod h1:dd8aDIUG1vDPP5r+vHBtiUK0Zn6uk3SsWt1ZvmCCHLs= -github.com/gospider007/tools v0.0.0-20250529114105-be4d4dbf36a2 h1:w5KTBR3sR3o/MCQjLLTgDIWQF3pZwkN3P65viwxv0BE= -github.com/gospider007/tools v0.0.0-20250529114105-be4d4dbf36a2/go.mod h1:gGaFJtYG/UPq+HVYhhVGhSOmF6NZMRayw3FflTOb27g= +github.com/gospider007/tools v0.0.0-20250610060552-2e45eaa25022 h1:IPoXe0+GyHjiIPn0Qy7nElpJ81awXUWrCoNholizqV4= +github.com/gospider007/tools v0.0.0-20250610060552-2e45eaa25022/go.mod h1:x7fyDzsG7lPJO6Q3D6DIzdUA+J9RAQoyOdmcP1XQF1k= github.com/gospider007/websocket v0.0.0-20250429035144-b1cf6819063a h1:DJMk+oALIJg3ArN5/DIPrQagWQL1Qi/c3DlXT9l1dGo= github.com/gospider007/websocket v0.0.0-20250429035144-b1cf6819063a/go.mod h1:0yVYF7b5kRayyUzAVgg6h1x+eZujKoSaA4n2krG5F7g= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -242,8 +242,8 @@ github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= -go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= +go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -271,8 +271,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -281,12 +281,12 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b h1:QoALfVG9rhQ/M7vYDScfPdWjGL9dlsVVM5VGh7aKoAA= -golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= +golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4= +golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w= -golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g= +golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE= +golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY= 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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -309,8 +309,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -334,8 +334,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -353,8 +353,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -391,6 +391,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -404,8 +406,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= @@ -439,8 +441,8 @@ golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/http.go b/http.go index 2a354ec..7b48c7c 100644 --- a/http.go +++ b/http.go @@ -82,16 +82,15 @@ func (obj *clientConn) send(req *http.Request, orderHeaders []interface { defer func() { obj.readWriteCtx.readCnl(readErr) }() - noBody := res.Body == nil || (res.ContentLength == -1 && len(res.TransferEncoding) == 0) - if !noBody { + if res.Body != nil { _, readErr = io.Copy(pw, rawBody) } - pw.CloseWithError(readErr) if readErr != nil && readErr != io.EOF && readErr != io.ErrUnexpectedEOF { err = tools.WrapError(readErr, "failed to read response body") } else { readErr = nil } + pw.CloseWithError(readErr) if readErr != nil { obj.CloseWithError(readErr) } else { diff --git a/roundTripper.go b/roundTripper.go index 32b168f..232d839 100644 --- a/roundTripper.go +++ b/roundTripper.go @@ -146,6 +146,7 @@ func (obj *roundTripper) ghttp3Dial(ctx *Response, remoteAddress Address, proxyA if err != nil { return nil, err } + conn = obj.newConnecotr() conn.Conn, err = http3.NewClient(netConn, func() { conn.forceCnl(errors.New("http3 client close")) @@ -160,7 +161,11 @@ func (obj *roundTripper) ghttp3Dial(ctx *Response, remoteAddress Address, proxyA return } -func (obj *roundTripper) uhttp3Dial(ctx *Response, spec uquic.QUICSpec, remoteAddress Address, proxyAddress ...Address) (conn *connecotr, err error) { +func (obj *roundTripper) uhttp3Dial(ctx *Response, remoteAddress Address, proxyAddress ...Address) (conn *connecotr, err error) { + spec, err := ja3.CreateUSpec(ctx.option.USpec) + if err != nil { + return nil, err + } udpConn, err := obj.http3Dial(ctx, remoteAddress, proxyAddress...) if err != nil { return nil, err @@ -201,6 +206,36 @@ func (obj *roundTripper) uhttp3Dial(ctx *Response, spec uquic.QUICSpec, remoteAd return } +// func (obj *roundTripper) thttp3Dial(ctx *Response, remoteAddress Address, proxyAddress ...Address) (conn *connecotr, err error) { +// // var rawNetConn net.Conn + +// // if len(proxys) > 0 { +// // comp := proxys[len(proxys)-1] +// // if comp.Compression != "" { +// // arch, err = NewCompression(comp.Compression, CompressionLevelBest) +// // if err != nil { +// // return nil, err +// // } +// // } +// // _, rawNetConn, err = obj.dialer.DialProxyContext(ctx, "tcp", ctx.option.TlsConfig.Clone(), append(proxys, remoteAddress)...) +// // } else { +// // var remoteAddress Address +// // remoteAddress, err = GetAddressWithUrl(ctx.request.URL) +// // if err != nil { +// // return nil, err +// // } +// // rawNetConn, err = obj.dialer.DialContext(ctx, "tcp", remoteAddress) +// // } +// // defer func() { +// // if err != nil && rawNetConn != nil { +// // rawNetConn.Close() +// // } +// // }() +// // if err != nil { +// // return nil, err +// // } +// } + func (obj *roundTripper) dial(ctx *Response) (conn *connecotr, err error) { proxys, err := obj.initProxys(ctx) if err != nil { @@ -212,18 +247,21 @@ func (obj *roundTripper) dial(ctx *Response) (conn *connecotr, err error) { } if ctx.option.ForceHttp3 { if ctx.option.USpec != nil { - spec, err := ja3.CreateUSpec(ctx.option.USpec) + return obj.uhttp3Dial(ctx, remoteAddress, proxys...) + } else { + return obj.ghttp3Dial(ctx, remoteAddress, proxys...) + } + } + var rawNetConn net.Conn + var arch Compression + if len(proxys) > 0 { + comp := proxys[len(proxys)-1] + if comp.Compression != "" { + arch, err = NewCompression(comp.Compression, CompressionLevelBest) if err != nil { return nil, err } - if spec.ClientHelloSpec != nil { - return obj.uhttp3Dial(ctx, spec, remoteAddress, proxys...) - } } - return obj.ghttp3Dial(ctx, remoteAddress, proxys...) - } - var rawNetConn net.Conn - if len(proxys) > 0 { _, rawNetConn, err = obj.dialer.DialProxyContext(ctx, "tcp", ctx.option.TlsConfig.Clone(), append(proxys, remoteAddress)...) } else { var remoteAddress Address @@ -260,6 +298,12 @@ func (obj *roundTripper) dial(ctx *Response) (conn *connecotr, err error) { } else { conne.c = rawNetConn } + if arch != nil { + conne.c, err = NewCompressionConn(conne.c, arch) + if err != nil { + return nil, err + } + } err = obj.dialConnecotr(ctx, conne, h2) if err != nil { return nil, err diff --git a/rw.go b/rw.go index 8c8c2b5..7178a52 100644 --- a/rw.go +++ b/rw.go @@ -3,7 +3,6 @@ package requests import ( "errors" "io" - "log" ) type wrapBody struct { @@ -33,9 +32,6 @@ func (obj *wrapBody) Close() error { // safe close conn func (obj *wrapBody) CloseConn() { - log.Print("111") obj.conn.forceCnl(errors.New("readWriterCloser close conn")) - log.Print("222") obj.conn.CloseWithError(errConnectionForceClosed) - log.Print("333") } diff --git a/socks5.go b/socks5.go index c2a2f1c..809e1e0 100644 --- a/socks5.go +++ b/socks5.go @@ -85,6 +85,12 @@ func (a Address) String() string { func (a Address) Network() string { return a.NetWork } +func (a Address) IsZero() bool { + if a.Port == 0 && a.Host == "" && len(a.IP) == 0 && a.NetWork == "" { + return true + } + return false +} type UDPConn struct { ctx context.Context diff --git a/tools.go b/tools.go index 76dc584..4d54944 100644 --- a/tools.go +++ b/tools.go @@ -54,6 +54,8 @@ func GetAddressWithUrl(uurl *url.URL) (addr Address, err error) { addr.Port = 80 case "https": addr.Port = 443 + case "ssh": + addr.Port = 22 case "socks5": addr.Port = 1080 } @@ -93,6 +95,8 @@ func GetAddressWithReq(req *http.Request) (addr Address, err error) { addr.Port = 80 case "https": addr.Port = 443 + case "ssh": + addr.Port = 22 case "socks5": addr.Port = 1080 // default: