Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for HTTPS proxy URL #1

Merged
merged 2 commits into from
Jul 10, 2019
Merged

add support for HTTPS proxy URL #1

merged 2 commits into from
Jul 10, 2019

Conversation

eli-darkly
Copy link

Background (short version): We need to support routing all HTTP connections through a proxy server that uses NTLM authentication. That's a bit tricky to do in Go, so we've been using this package. However, it only works if the connection to the proxy (as opposed to the connection from the proxy to the ultimate target URL) is insecure. This PR adds support for an HTTPS proxy URL (and, optionally, custom TLS configuration).

Background (long version):

  • In Go, the regular HTTP proxy mechanism lets you specify a proxy URL and optional authentication header(s).
  • However, NTLM authentication doesn't consist of just adding a header to the proxy request; it requires multiple requests to the proxy. That's not something the Go HTTP client knows how to do.
  • The Go HTTP client does allow you to override the function for establishing the TCP connection: DialContext. So the approach used in this package is to decorate DialContext with logic that does all of the proxy communication after the connection is established. The Go HTTP client doesn't even know you're using a proxy.
  • However, to establish the proxy connection, it's calling the default DialContext. That will not do TLS - it just takes a hostname and port, it has no way to know if should be a secure connection. In normal usage, if you override DialContext you don't need to worry about that, because the HTTP client knows it's supposed to be a secure connection and add the TLS logic after DialContext returns. But that's no good for our purposes because we need to communicate with the proxy server within our custom DialContext, and that communication needs to be secure.
  • So, this PR changes it to only call the default DialContext if the proxy URL is HTTP; if it's HTTPS, we instead call tls.DialWithDialer().

@eli-darkly
Copy link
Author

eli-darkly commented Jul 2, 2019

I haven't set up an actual NTLM-authenticated proxy server with an HTTPS endpoint, but I've tested this against a fake proxy that just puts up a HTTPS listener but doesn't actually proxy anything, and I can verify that it at least connects correctly and is able to send the initial request. Before we release this in any production code, I plan to add end-to-end unit tests for this package.

return func(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := dialContext(ctx, network, proxyAddress)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this logic has been factored out into dialAndNegotiate, with no changes except the first line.

@eli-darkly eli-darkly merged commit 22cdb55 into master Jul 10, 2019
@eli-darkly eli-darkly deleted the eb/allow-https-proxy branch July 10, 2019 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants