2023-10-05 11:32:25 +00:00
|
|
|
// Package easyproxy provides a method to quickly create a http.Transport or net.Conn using given proxy details (SOCKS5 or HTTP).
|
2023-10-05 10:25:58 +00:00
|
|
|
package easyproxy
|
|
|
|
|
|
|
|
import (
|
2023-10-05 11:32:25 +00:00
|
|
|
"crypto/tls"
|
2023-10-05 10:25:58 +00:00
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
|
2023-10-05 11:32:25 +00:00
|
|
|
"github.com/magisterquis/connectproxy"
|
2023-10-05 10:25:58 +00:00
|
|
|
"golang.org/x/net/proxy"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Protocol int
|
|
|
|
|
|
|
|
const (
|
|
|
|
SOCKS5 Protocol = iota // SOCKS5
|
|
|
|
HTTP // HTTP
|
|
|
|
)
|
|
|
|
|
2023-10-05 11:32:25 +00:00
|
|
|
type ProxyConfig struct {
|
|
|
|
Protocol Protocol
|
|
|
|
Addr string
|
|
|
|
User string
|
|
|
|
Password string
|
|
|
|
}
|
|
|
|
|
2023-10-05 10:25:58 +00:00
|
|
|
// NewTransport returns a http.Transport using the given proxy details. Leave user/pass blank if not needed.
|
2023-10-05 11:32:25 +00:00
|
|
|
func NewTransport(c ProxyConfig) (*http.Transport, error) {
|
2023-10-05 10:25:58 +00:00
|
|
|
t := &http.Transport{}
|
2023-10-05 11:32:25 +00:00
|
|
|
if c.Protocol == HTTP {
|
2023-10-05 10:25:58 +00:00
|
|
|
u := &url.URL{
|
|
|
|
Scheme: "http",
|
2023-10-05 11:32:25 +00:00
|
|
|
Host: c.Addr,
|
2023-10-05 10:25:58 +00:00
|
|
|
}
|
2023-10-05 11:32:25 +00:00
|
|
|
if c.User != "" && c.Password != "" {
|
|
|
|
u.User = url.UserPassword(c.User, c.Password)
|
2023-10-05 10:25:58 +00:00
|
|
|
}
|
|
|
|
t.Proxy = http.ProxyURL(u)
|
|
|
|
return t, nil
|
|
|
|
}
|
|
|
|
var auth *proxy.Auth = nil
|
2023-10-05 11:32:25 +00:00
|
|
|
if c.User != "" && c.Password != "" {
|
|
|
|
auth = &proxy.Auth{User: c.User, Password: c.Password}
|
2023-10-05 10:25:58 +00:00
|
|
|
}
|
2023-10-05 11:32:25 +00:00
|
|
|
dialer, err := proxy.SOCKS5("tcp", c.Addr, auth, proxy.Direct)
|
2023-10-05 10:25:58 +00:00
|
|
|
if err != nil {
|
2023-10-05 11:32:25 +00:00
|
|
|
return nil, err
|
2023-10-05 10:25:58 +00:00
|
|
|
}
|
|
|
|
t.Dial = dialer.Dial
|
|
|
|
return t, nil
|
|
|
|
}
|
2023-10-05 11:32:25 +00:00
|
|
|
|
|
|
|
// NewConn returns a tls.Conn to "addr" using the given proxy details. Leave user/pass blank if not needed.
|
|
|
|
func NewConn(c ProxyConfig, addr string, tlsConf *tls.Config) (*tls.Conn, error) {
|
|
|
|
var proxyDialer proxy.Dialer
|
|
|
|
var err error
|
|
|
|
if c.Protocol == SOCKS5 {
|
|
|
|
var auth *proxy.Auth = nil
|
|
|
|
if c.User != "" && c.Password != "" {
|
|
|
|
auth = &proxy.Auth{User: c.User, Password: c.Password}
|
|
|
|
}
|
|
|
|
proxyDialer, err = proxy.SOCKS5("tcp", c.Addr, auth, proxy.Direct)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
u := &url.URL{
|
|
|
|
Scheme: "http",
|
|
|
|
Host: c.Addr,
|
|
|
|
}
|
|
|
|
if c.User != "" && c.Password != "" {
|
|
|
|
u.User = url.UserPassword(c.User, c.Password)
|
|
|
|
}
|
|
|
|
proxyDialer, err = connectproxy.New(u, proxy.Direct)
|
|
|
|
}
|
|
|
|
|
|
|
|
dialer, err := proxyDialer.Dial("tcp", addr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
conn := tls.Client(dialer, tlsConf)
|
|
|
|
return conn, nil
|
|
|
|
}
|