github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/lib/proxy/socks.go (about)

     1  // Package proxy enables SOCKS5 proxy dialling
     2  package proxy
     3  
     4  import (
     5  	"fmt"
     6  	"net"
     7  	"strings"
     8  
     9  	"golang.org/x/net/proxy"
    10  )
    11  
    12  // SOCKS5Dial dials a net.Conn using a SOCKS5 proxy server.
    13  // The socks5Proxy address can be in the form of [user:password@]host:port, [user@]host:port or just host:port if no auth is required.
    14  // It will optionally take a proxyDialer to dial the SOCKS5 proxy server. If nil is passed, it will use the default net.Dialer.
    15  func SOCKS5Dial(network, addr, socks5Proxy string, proxyDialer proxy.Dialer) (net.Conn, error) {
    16  
    17  	if proxyDialer == nil {
    18  		proxyDialer = &net.Dialer{}
    19  	}
    20  	var (
    21  		proxyAddress string
    22  		proxyAuth    *proxy.Auth
    23  	)
    24  	if credsAndHost := strings.SplitN(socks5Proxy, "@", 2); len(credsAndHost) == 2 {
    25  		proxyCreds := strings.SplitN(credsAndHost[0], ":", 2)
    26  		proxyAuth = &proxy.Auth{
    27  			User: proxyCreds[0],
    28  		}
    29  		if len(proxyCreds) == 2 {
    30  			proxyAuth.Password = proxyCreds[1]
    31  		}
    32  		proxyAddress = credsAndHost[1]
    33  	} else {
    34  		proxyAddress = credsAndHost[0]
    35  	}
    36  	proxyDialer, err := proxy.SOCKS5("tcp", proxyAddress, proxyAuth, proxyDialer)
    37  	if err != nil {
    38  		return nil, fmt.Errorf("failed to create proxy dialer: %w", err)
    39  	}
    40  	return proxyDialer.Dial(network, addr)
    41  
    42  }