From 4c34d8ba5a27487ed2fb1ee9661b801ee7b535b0 Mon Sep 17 00:00:00 2001 From: gospider <2216403312@qq.com> Date: Fri, 3 Jan 2025 21:14:18 +0800 Subject: [PATCH] sync --- dial.go | 45 ++++------ roundTripper.go | 29 +++---- socks5.go | 85 ++++--------------- test/proxy/chain_proxy_test.go | 36 ++++++++ test/proxy/http3_proxy_test.go | 33 ++++++- test/{ => response}/request/data_test.go | 0 test/{ => response}/request/file_test.go | 0 test/{ => response}/request/form_test.go | 0 test/{ => response}/request/json_test.go | 0 test/{ => response}/request/localAddr_test.go | 0 test/{ => response}/request/method_test.go | 0 test/{ => response}/request/params_test.go | 0 test/{ => response}/request/stream_test.go | 0 13 files changed, 110 insertions(+), 118 deletions(-) rename test/{ => response}/request/data_test.go (100%) rename test/{ => response}/request/file_test.go (100%) rename test/{ => response}/request/form_test.go (100%) rename test/{ => response}/request/json_test.go (100%) rename test/{ => response}/request/localAddr_test.go (100%) rename test/{ => response}/request/method_test.go (100%) rename test/{ => response}/request/params_test.go (100%) rename test/{ => response}/request/stream_test.go (100%) diff --git a/dial.go b/dial.go index 9341ac3..0a0a067 100644 --- a/dial.go +++ b/dial.go @@ -146,44 +146,28 @@ func (obj *Dialer) ProxyDialContext(ctx context.Context, ctxData *RequestOption, return obj.dialContext(ctx, ctxData, network, addr, true) } -func (obj *Dialer) DialProxyContext(ctx context.Context, ctxData *RequestOption, network string, proxyTlsConfig *tls.Config, proxyUrls ...Address) (net.Conn, error) { +func (obj *Dialer) DialProxyContext(ctx context.Context, ctxData *RequestOption, network string, proxyTlsConfig *tls.Config, proxyUrls ...Address) (net.PacketConn, net.Conn, error) { proxyLen := len(proxyUrls) if proxyLen < 2 { - return nil, errors.New("proxyUrls is nil") + return nil, nil, errors.New("proxyUrls is nil") } var conn net.Conn var err error + var packCon net.PacketConn for index := range proxyLen - 1 { oneProxy := proxyUrls[index] remoteUrl := proxyUrls[index+1] if index == 0 { conn, err = obj.dialProxyContext(ctx, ctxData, network, oneProxy) if err != nil { - return conn, err + return packCon, conn, err } } - conn, err = obj.verifyProxyToRemote(ctx, ctxData, conn, proxyTlsConfig, oneProxy, remoteUrl) + packCon, conn, err = obj.verifyProxyToRemote(ctx, ctxData, conn, proxyTlsConfig, oneProxy, remoteUrl, index == proxyLen-2) } - return conn, err + return packCon, conn, err } -// func getProxyAddr(proxyUrl *url.URL) (addr string, err error) { -// if proxyUrl.Port() == "" { -// switch proxyUrl.Scheme { -// case "http": -// addr = net.JoinHostPort(proxyUrl.Hostname(), "80") -// case "https": -// addr = net.JoinHostPort(proxyUrl.Hostname(), "443") -// case "socks5": -// addr = net.JoinHostPort(proxyUrl.Hostname(), "1080") -// default: -// return "", errors.New("not support scheme") -// } -// } else { -// addr = net.JoinHostPort(proxyUrl.Hostname(), proxyUrl.Port()) -// } -// return -// } func (obj *Dialer) dialProxyContext(ctx context.Context, ctxData *RequestOption, network string, proxyUrl Address) (net.Conn, error) { if ctxData == nil { ctxData = &RequestOption{} @@ -191,11 +175,12 @@ func (obj *Dialer) dialProxyContext(ctx context.Context, ctxData *RequestOption, return obj.ProxyDialContext(ctx, ctxData, network, proxyUrl) } -func (obj *Dialer) verifyProxyToRemote(ctx context.Context, option *RequestOption, conn net.Conn, proxyTlsConfig *tls.Config, proxyAddress Address, remoteAddress Address) (net.Conn, error) { +func (obj *Dialer) verifyProxyToRemote(ctx context.Context, option *RequestOption, conn net.Conn, proxyTlsConfig *tls.Config, proxyAddress Address, remoteAddress Address, isLast bool) (net.PacketConn, net.Conn, error) { var err error + var packCon net.PacketConn if proxyAddress.Scheme == "https" { if conn, err = obj.addTls(ctx, conn, proxyAddress.Host, true, proxyTlsConfig); err != nil { - return conn, err + return packCon, conn, err } if option.Logger != nil { option.Logger(Log{ @@ -220,12 +205,16 @@ func (obj *Dialer) verifyProxyToRemote(ctx context.Context, option *RequestOptio }) } case "socks5": - err = obj.verifyTCPSocks5(conn, proxyAddress, remoteAddress) + if isLast && option.H3 { + packCon, err = obj.verifyUDPSocks5(ctx, conn, proxyAddress, remoteAddress) + } else { + err = obj.verifyTCPSocks5(conn, proxyAddress, remoteAddress) + } if option.Logger != nil { option.Logger(Log{ Id: option.requestId, Time: time.Now(), - Type: LogType_ProxyTCPConnect, + Type: LogType_ProxyConnectRemote, Msg: remoteAddress.String(), }) } @@ -234,9 +223,9 @@ func (obj *Dialer) verifyProxyToRemote(ctx context.Context, option *RequestOptio }() select { case <-ctx.Done(): - return conn, context.Cause(ctx) + return packCon, conn, context.Cause(ctx) case <-done: - return conn, err + return packCon, conn, err } } func (obj *Dialer) loadHost(ctx context.Context, host string, option *RequestOption) (net.IP, error) { diff --git a/roundTripper.go b/roundTripper.go index e1c1744..fdf08d7 100644 --- a/roundTripper.go +++ b/roundTripper.go @@ -90,20 +90,21 @@ func (obj *roundTripper) newConnecotr() *connecotr { return conne } -func (obj *roundTripper) http3Dial(ctx context.Context, option *RequestOption, proxyAddress Address, remtoeAddress Address) (udpConn net.PacketConn, err error) { - if !proxyAddress.Nil() { - if proxyAddress.Scheme != "socks5" { - err = errors.New("http3 only socks5 proxy supported") +func (obj *roundTripper) http3Dial(ctx context.Context, option *RequestOption, remtoeAddress Address, proxyAddress ...Address) (udpConn net.PacketConn, err error) { + if len(proxyAddress) > 0 { + if proxyAddress[len(proxyAddress)-1].Scheme != "socks5" { + err = errors.New("http3 last proxy must socks5 proxy") return } - udpConn, err = obj.dialer.Socks5UdpProxy(ctx, option, proxyAddress, remtoeAddress) + // udpConn, err = obj.dialer.Socks5UdpProxy(ctx, option, remtoeAddress, proxyAddress...) + udpConn, _, err = obj.dialer.DialProxyContext(ctx, option, "tcp", option.TlsConfig.Clone(), append(proxyAddress, remtoeAddress)...) } else { udpConn, err = net.ListenUDP("udp", nil) } return } -func (obj *roundTripper) ghttp3Dial(ctx context.Context, option *RequestOption, proxyAddress Address, remoteAddress Address) (conn *connecotr, err error) { - udpConn, err := obj.http3Dial(ctx, option, proxyAddress, remoteAddress) +func (obj *roundTripper) ghttp3Dial(ctx context.Context, option *RequestOption, remoteAddress Address, proxyAddress ...Address) (conn *connecotr, err error) { + udpConn, err := obj.http3Dial(ctx, option, remoteAddress, proxyAddress...) if err != nil { return nil, err } @@ -124,8 +125,8 @@ func (obj *roundTripper) ghttp3Dial(ctx context.Context, option *RequestOption, return } -func (obj *roundTripper) uhttp3Dial(ctx context.Context, option *RequestOption, proxyAddress Address, remoteAddress Address) (conn *connecotr, err error) { - udpConn, err := obj.http3Dial(ctx, option, proxyAddress, remoteAddress) +func (obj *roundTripper) uhttp3Dial(ctx context.Context, option *RequestOption, remoteAddress Address, proxyAddress ...Address) (conn *connecotr, err error) { + udpConn, err := obj.http3Dial(ctx, option, remoteAddress, proxyAddress...) if err != nil { return nil, err } @@ -156,19 +157,15 @@ func (obj *roundTripper) dial(option *RequestOption, req *http.Request) (conn *c return nil, err } if option.H3 { - var proxyUrl Address - if len(proxys) > 0 { - proxyUrl = proxys[0] - } if option.Ja3Spec.IsSet() { - return obj.uhttp3Dial(req.Context(), option, proxyUrl, remoteAddress) + return obj.uhttp3Dial(req.Context(), option, remoteAddress, proxys...) } else { - return obj.ghttp3Dial(req.Context(), option, proxyUrl, remoteAddress) + return obj.ghttp3Dial(req.Context(), option, remoteAddress, proxys...) } } var netConn net.Conn if len(proxys) > 0 { - netConn, err = obj.dialer.DialProxyContext(req.Context(), option, "tcp", option.TlsConfig.Clone(), append(proxys, remoteAddress)...) + _, netConn, err = obj.dialer.DialProxyContext(req.Context(), option, "tcp", option.TlsConfig.Clone(), append(proxys, remoteAddress)...) } else { var remoteAddress Address remoteAddress, err = GetAddressWithUrl(req.URL) diff --git a/socks5.go b/socks5.go index 09b4a10..671ecf4 100644 --- a/socks5.go +++ b/socks5.go @@ -12,8 +12,8 @@ import ( ) var ( - errBadHeader = errors.New("bad header") - errUnsupportedMethod = errors.New("unsupported method") + errBadHeader = errors.New("bad header") + // errUnsupportedMethod = errors.New("unsupported method") ) const MaxUdpPacket int = math.MaxUint16 - 28 @@ -94,10 +94,6 @@ func (a Address) String() string { func (a Address) Network() string { return a.NetWork } -func (a Address) Nil() bool { - return a.IP == nil && a.Name == "" -} - func ReadUdpAddr(r io.Reader) (Address, error) { UdpAddress := Address{} var addrType [1]byte @@ -146,11 +142,13 @@ type UDPConn struct { // defaultTarget net.Addr prefix []byte net.PacketConn + UDPConn *net.UDPConn } -func NewUDPConn(raw net.PacketConn, proxyAddress net.Addr) (*UDPConn, error) { +func NewUDPConn(packConn net.PacketConn, proxyAddress net.Addr) (*UDPConn, error) { conn := &UDPConn{ - PacketConn: raw, + PacketConn: packConn, + UDPConn: packConn.(*net.UDPConn), proxyAddress: proxyAddress, prefix: []byte{0, 0, 0}, } @@ -229,83 +227,30 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { // return c.defaultTarget // } -// SetReadBuffer implements the net.UDPConn SetReadBuffer method. func (c *UDPConn) SetReadBuffer(bytes int) error { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return errUnsupportedMethod - } - return udpConn.SetReadBuffer(bytes) + return c.UDPConn.SetReadBuffer(bytes) } - -// SetWriteBuffer implements the net.UDPConn SetWriteBuffer method. func (c *UDPConn) SetWriteBuffer(bytes int) error { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return errUnsupportedMethod - } - return udpConn.SetWriteBuffer(bytes) + return c.UDPConn.SetWriteBuffer(bytes) } - -// SetDeadline implements the Conn SetDeadline method. func (c *UDPConn) SetDeadline(t time.Time) error { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return errUnsupportedMethod - } - return udpConn.SetDeadline(t) + return c.UDPConn.SetDeadline(t) } - -// SetReadDeadline implements the Conn SetReadDeadline method. func (c *UDPConn) SetReadDeadline(t time.Time) error { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return errUnsupportedMethod - } - return udpConn.SetReadDeadline(t) + return c.UDPConn.SetReadDeadline(t) } - -// SetWriteDeadline implements the Conn SetWriteDeadline method. func (c *UDPConn) SetWriteDeadline(t time.Time) error { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return errUnsupportedMethod - } - return udpConn.SetWriteDeadline(t) + return c.UDPConn.SetWriteDeadline(t) } - -// ReadFromUDP implements the net.UDPConn ReadFromUDP method. func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return 0, nil, errUnsupportedMethod - } - return udpConn.ReadFromUDP(b) + return c.UDPConn.ReadFromUDP(b) } - -// ReadMsgUDP implements the net.UDPConn ReadMsgUDP method. func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error) { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return 0, 0, 0, nil, errUnsupportedMethod - } - return udpConn.ReadMsgUDP(b, oob) + return c.UDPConn.ReadMsgUDP(b, oob) } - -// WriteToUDP implements the net.UDPConn WriteToUDP method. func (c *UDPConn) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return 0, errUnsupportedMethod - } - return udpConn.WriteToUDP(b, addr) + return c.UDPConn.WriteToUDP(b, addr) } - -// WriteMsgUDP implements the net.UDPConn WriteMsgUDP method. func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) { - udpConn, ok := c.PacketConn.(*net.UDPConn) - if !ok { - return 0, 0, errUnsupportedMethod - } - return udpConn.WriteMsgUDP(b, oob, addr) + return c.UDPConn.WriteMsgUDP(b, oob, addr) } diff --git a/test/proxy/chain_proxy_test.go b/test/proxy/chain_proxy_test.go index 2d500c0..c5fc7d7 100644 --- a/test/proxy/chain_proxy_test.go +++ b/test/proxy/chain_proxy_test.go @@ -2,11 +2,47 @@ package main import ( "context" + "log" "testing" + "github.com/gospider007/proxy" "github.com/gospider007/requests" ) +func TestProxy2(t *testing.T) { + proCliPre, err := proxy.NewClient(nil, proxy.ClientOption{ + DisVerify: true, + }) + if err != nil { + t.Fatal(err) + } + defer proCliPre.Close() + go proCliPre.Run() + proIp := "http://" + proCliPre.Addr() + + proCli, err := proxy.NewClient(nil, proxy.ClientOption{ + DisVerify: true, + }) + if err != nil { + t.Fatal(err) + } + defer proCli.Close() + go proCli.Run() + proIp2 := "http://" + proCli.Addr() + reqCli, err := requests.NewClient(nil) + if err != nil { + t.Fatal(err) + } + resp, err := reqCli.Request(nil, "get", "https://httpbin.org/ip", requests.RequestOption{Proxys: []string{ + proIp, + proIp2, + }}) + if err != nil { + t.Fatal(err) + } + log.Print(resp.Text()) +} + func TestChainProxy(t *testing.T) { resp, err := requests.Get(context.TODO(), "https://httpbin.org/anything", requests.RequestOption{ Proxys: []string{}, //set proxy,ex:"http://127.0.0.1:8080","https://127.0.0.1:8080","socks5://127.0.0.1:8080" diff --git a/test/proxy/http3_proxy_test.go b/test/proxy/http3_proxy_test.go index da760dd..79ba3a0 100644 --- a/test/proxy/http3_proxy_test.go +++ b/test/proxy/http3_proxy_test.go @@ -18,6 +18,7 @@ import ( var ( proxyHost = "127.0.0.1:1080" + proxyHost2 = "127.0.0.1:10801" remoteHost = "127.0.0.1:8080" ) @@ -41,6 +42,28 @@ func client() { time.Sleep(time.Second) } } +func client2() { + for range 5 { + resp, err := requests.Post(nil, "https://"+remoteHost, requests.RequestOption{ + H3: true, + Logger: func(l requests.Log) { + log.Print(l) + }, + Proxys: []string{ + "http://" + proxyHost, + "socks5://" + proxyHost, + }, + Body: []byte("hello, server!"), + }) + if err != nil { + fmt.Println(err) + continue + } + fmt.Println(resp.StatusCode()) + fmt.Println(resp.Text()) + time.Sleep(time.Second) + } +} func server() { mux := http.NewServeMux() @@ -74,9 +97,9 @@ func server() { fmt.Println("Server is listening...") fmt.Println(server.ListenAndServe()) } -func proxyServer() { +func proxyServer(addr string) { c, err := proxy.NewClient(nil, proxy.ClientOption{ - Addr: ":1080", + Addr: addr, Debug: true, DisVerify: true, }) @@ -88,7 +111,9 @@ func proxyServer() { func TestHttp3Proxy(t *testing.T) { go server() - go proxyServer() + go proxyServer(proxyHost) + go proxyServer(proxyHost2) time.Sleep(time.Second * 3) - client() + // client() + client2() } diff --git a/test/request/data_test.go b/test/response/request/data_test.go similarity index 100% rename from test/request/data_test.go rename to test/response/request/data_test.go diff --git a/test/request/file_test.go b/test/response/request/file_test.go similarity index 100% rename from test/request/file_test.go rename to test/response/request/file_test.go diff --git a/test/request/form_test.go b/test/response/request/form_test.go similarity index 100% rename from test/request/form_test.go rename to test/response/request/form_test.go diff --git a/test/request/json_test.go b/test/response/request/json_test.go similarity index 100% rename from test/request/json_test.go rename to test/response/request/json_test.go diff --git a/test/request/localAddr_test.go b/test/response/request/localAddr_test.go similarity index 100% rename from test/request/localAddr_test.go rename to test/response/request/localAddr_test.go diff --git a/test/request/method_test.go b/test/response/request/method_test.go similarity index 100% rename from test/request/method_test.go rename to test/response/request/method_test.go diff --git a/test/request/params_test.go b/test/response/request/params_test.go similarity index 100% rename from test/request/params_test.go rename to test/response/request/params_test.go diff --git a/test/request/stream_test.go b/test/response/request/stream_test.go similarity index 100% rename from test/request/stream_test.go rename to test/response/request/stream_test.go