proxyplease

package module
v0.0.0-...-93f24a2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2023 License: MIT Imports: 17 Imported by: 0

README

proxyplease

Ask nicely, and you might get proxied.

proxyplease is a Go package that attempts to establish a valid proxy connection based on available assumptions. It does by using native and third-party libraries. proxyplease returns a DialContext which can be used in an http.Client Transport or other contexts.

Examples

You can assume the complete proxy configuration and authentication from system.

dialContext := proxyplease.NewDialContext(proxyplease.Proxy{})

Or maybe you want to specify a specific SOCKS5 proxy:

u, _ := url.Parse("socks5h://localhost:1080")
dialContext := proxyplease.NewDialContext(proxyplease.Proxy{URL: u})

Let's try a HTTP CONNECT Proxy. This proxy requires NTLM authentication. We don't know the user's credentials so we will assume the credentials from the current user session via SSPI (Windows only).

u, _ := url.Parse("http://proxy.example.com:8888")
dialContext := proxyplease.NewDialContext(proxyplease.Proxy{URL: u})

Or maybe you want to use specific credentials for NTLM authentication. Oh, but you forgot proxy URL. If the system was configured with a proxy URL, you'll still get proxied:

dialContext := proxyplease.NewDialContext(proxyplease.Proxy{Username: "foo", Password: "bar", Domain: "EXAMPLE"})

Oh no! This user's proxy only supported Basic authentication. Don't worry. The above example still covers you if those credentials are valid.

But what if you need a specific user-agent. Easy!

h := &http.Header{}
h.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0")
dialContext := proxyplease.NewDialContext(proxyplease.Proxy{Headers: h})

What if the proxy depends on the target URL and you need to look up via PAC?

t, _ := url.Parse("https://www.google.com")
dialContext := proxyplease.NewDialContext(proxyplease.Proxy{TargetURL: t})

Proxy Support

SOCKS
Protocol URI No Auth User / Pass GSSAPI DNS
SOCKS4 socks4:// ✔️
SOCKS4a socks4a:// ✔️ ✔️
SOCKS5 socks5:// ✔️ ✔️ ✔️
SOCKS5h socks5h:// ✔️ ✔️ ✔️

The golang.org/x/net/proxy will always do remote DNS for socks5://.

HTTP CONNECT
Protocol URI No Auth Basic NTLM Negotiate::Kerberos Negotiate::NTLM Kerberos Digest
HTTP http:// ✔️ ✔️ ✔️ ✔️
HTTPS https:// ✔️ ✔️ ✔️ ✔️

If the proxy iniitally responds with a 407 Proxy Authentication Required, the Proxy-Authenticate header(s) will be inspected for authentication schemes supported by the server. Each authentication scheme will be attempted in order of response until a 200 Connection Established. If no credentials are supplied, proxyplease will attempt to transparently assume the current user's credentials from SSPI (SSPI is supported on Windows only and used for NTLM, Kerberos and Negotiate authentications schemes) or if they are hardcoded in environemt variables. Ex: HTTP_PROXY=http://foo:bar@example.com:3128. If proxyplease does not have enough information to attempt the authentication, the attempt will fail and another scheme will be attempted.

Proxy Selection

The proxy URL can be specified by passing a URL type. Example:

u, _ := url.Parse("socks5://localhost:8888")
dialContext := proxyplease.NewDialContext(proxyplease.Proxy{URL: u})

If a proxy URL is not provided, proxyplease will attempt to infer the URL from the system utilizing go-get-proxied. If a proxy cannot be determined, it will be assumed the connection is direct.

The proxy will be selected by the following priority:

Windows

  1. proxyplease.Proxy.URL
  2. Environment Variable: HTTPS_PROXY, HTTP_PROXY, FTP_PROXY, or ALL_PROXY. NO_PROXY is respected.
  3. Internet Options: Automatically detect settings (WPAD)
  4. Internet Options: Use automatic configuration script (PAC)
  5. Internet Options: Manual proxy server
  6. WINHTTP: (netsh winhttp)

Linux

  1. proxyplease.Proxy.URL
  2. Environment Variable: HTTPS_PROXY, HTTP_PROXY, FTP_PROXY, or ALL_PROXY. NO_PROXY is respected.

MacOS

  1. proxyplease.Proxy.URL
  2. Environment Variable: HTTPS_PROXY, HTTP_PROXY, FTP_PROXY, or ALL_PROXY. NO_PROXY is respected.
  3. Network Settings: scutil

Known Issues

  • The Negotiate authentication sequence is supposed to fallback to Negotiate::NTLM if Negotiate::Kerberbos fails. This is currently unsupported.
  • Digest authentication is currently unsupported
  • Pure Kerberos authentication is currently unsupported. (In most environments, Kerberos authentication is usually wrapped as Negotiate::Kerberos, which is supported)
  • Negotiate::Kerberos is currently only supported on Windows
  • No tests
  • No keyring support (example: Windows Credential Manager might have stored credentials to a SOCKS proxy)

References

The code for this project was heavily influenced by the following authors. Many thanks to them.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetDebugf

func SetDebugf(f func(format string, a ...interface{}))

SetDebugf sets a debugf function for debug output

Types

type DialContext

type DialContext func(ctx context.Context, network, addr string) (net.Conn, error)

DialContext is the DialContext function that should be wrapped with a a supported authentication scheme.

func NewDialContext

func NewDialContext(p Proxy) DialContext

NewDialContext returns a DialContext that can be used in a variety of network types. The function accepts an optional Proxy type parameter.

type Proxy

type Proxy struct {
	URL              *url.URL     // URL to proxy
	Username         string       // Username for authentication. This value is overridden if user is supplied in ProxyURL.
	Password         string       // Password for authentication. This value is overridden if pass is supplied in Proxy.URL.
	Domain           string       // Windows Domain. Used only for NTLM authentication.
	TargetURL        *url.URL     // Target URL for proxy. Used to look up proxy from a PAC provided by the environment.
	Headers          *http.Header // Add additional headers to the HTTP CONNECT request
	TLSConfig        *tls.Config  // Provide your own TLSConfig
	AuthSchemeFilter []string     // If nil, all authentication schemes will be attempted. Else, only the matching auth schemes will be used.
}

Proxy is a struct that can be passed to NewDialContext. All variables are optional. If a value is nil, a default will be assigned or inferred from the local system settings.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL