tss/proxy/proxy.go

82 lines
2.2 KiB
Go
Raw Normal View History

2022-04-29 13:38:49 -04:00
package proxy
import (
2022-05-02 11:36:24 -04:00
"context"
2022-04-29 13:38:49 -04:00
"fmt"
2022-05-02 11:36:24 -04:00
"net"
2022-04-29 13:38:49 -04:00
"net/http"
"net/url"
"golang.org/x/net/proxy"
)
2022-05-01 23:28:54 -04:00
func GetTransport(proxy string) (http.RoundTripper, error) {
2022-05-01 19:13:27 -04:00
if proxy == "" {
2022-05-01 23:28:54 -04:00
return http.DefaultTransport, nil
2022-05-01 19:13:27 -04:00
}
2022-04-29 13:38:49 -04:00
proxyUrl, err := url.Parse(proxy)
if err != nil {
return nil, fmt.Errorf("failed to parse proxyUrl, url:%s, err: %w", proxy, err)
}
if proxyUrl.Host == "unix" && proxyUrl.Scheme == "socks5" &&
len(proxyUrl.Path) > 1 /* Path cannot be empty or just / */ {
2022-05-23 12:45:25 -04:00
return unixSocks5Proxy(proxyUrl)
2022-04-29 13:38:49 -04:00
}
2022-05-02 11:36:24 -04:00
return proxyTcp(proxyUrl)
}
type forwardDialer struct {
dialContext func(ctx context.Context, network, address string) (net.Conn, error)
}
func (d *forwardDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
return d.dialContext(ctx, network, address)
}
func (d *forwardDialer) Dial(network, address string) (net.Conn, error) {
panic("Dial should not be called")
//default Dial is nil
//return defaultTransport().Dial(network, address)
2022-04-29 13:38:49 -04:00
}
2022-05-23 12:45:25 -04:00
func unixSocks5Proxy(proxyUrl *url.URL) (http.RoundTripper, error) {
2022-05-02 11:36:24 -04:00
trans := defaultTransport().Clone()
if trans.DialContext == nil {
panic("DefaultTransport has nil DialContext")
}
2022-05-23 12:45:25 -04:00
var auth *proxy.Auth
username := proxyUrl.User.Username()
password, _ := proxyUrl.User.Password()
// Both username and password should have atleast one char
if username != "" && password != "" {
auth = &proxy.Auth{
User: username,
Password: password,
}
}
dialer, err := proxy.SOCKS5("unix", proxyUrl.Path, auth, &forwardDialer{trans.DialContext})
2022-04-29 13:38:49 -04:00
if err != nil {
2022-05-23 12:45:25 -04:00
return nil, fmt.Errorf("failed to make socks proxy, url: %s, err: %w", proxyUrl, err)
2022-04-29 13:38:49 -04:00
}
ctxDialer, ok := dialer.(proxy.ContextDialer)
if !ok {
2022-05-01 19:13:27 -04:00
panic("proxy.SOCKS5 did not return a ContextDialer")
2022-04-29 13:38:49 -04:00
}
2022-05-01 19:13:27 -04:00
trans.DialContext = ctxDialer.DialContext
trans.Proxy = nil
2022-05-01 23:28:54 -04:00
return trans, nil
2022-04-29 13:38:49 -04:00
}
2022-05-02 11:36:24 -04:00
func proxyTcp(proxyUrl *url.URL) (http.RoundTripper, error) {
trans := defaultTransport().Clone()
2022-05-01 19:13:27 -04:00
trans.Proxy = http.ProxyURL(proxyUrl)
2022-05-01 23:28:54 -04:00
return trans, nil
2022-05-01 19:13:27 -04:00
}
func defaultTransport() *http.Transport {
transPtr, ok := http.DefaultTransport.(*http.Transport)
if !ok {
panic("http.DefaultTransport is not a *http.Transport")
}
2022-05-02 11:36:24 -04:00
return transPtr
2022-04-29 13:38:49 -04:00
}