This commit is contained in:
gospider
2025-01-03 21:14:18 +08:00
parent 34a416a1b0
commit 4c34d8ba5a
13 changed files with 110 additions and 118 deletions

45
dial.go
View File

@@ -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) {

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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"

View File

@@ -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()
}