mirror of
https://github.com/gospider007/requests.git
synced 2025-12-24 13:57:52 +08:00
sync
This commit is contained in:
45
dial.go
45
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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
85
socks5.go
85
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)
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user