-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Implements missing HTTPS proxy functionality #978
base: main
Are you sure you want to change the base?
Conversation
/cc @adrianosela |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this @seans3 🚀
IIUIC the same certificate is used for both the proxy and the backend, don't we need to handle the case when both are different? what happens if the proxy requires a different certificate than the backend? EDIT I see, the TLSConfig can be used for that, also @seans3 sent me this https://github.com/adrianosela/https-proxy/tree/main?tab=readme-ov-file#https-proxy |
client.go
Outdated
if proxyURL == nil { | ||
return nil, errors.New("generated proxy url is nil") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUIC this change the behavior, before if the returned proxyURL
was nil meant "this connections should not be proxied" and now it will error , I think this should be just a noop
if proxyURL == nil { | |
return nil, errors.New("generated proxy url is nil") | |
} | |
// this request should not be proxied and use the original dialer | |
if proxyURL == nil { | |
return netDial, nil | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
if proxyURL.Scheme == "http" && d.NetDialTLSContext != nil { | ||
return nil, errors.New("dial TLS function set for dialing non-HTTPS proxy") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not match the logic in
var netDial netDialerFunc
switch {
case u.Scheme == "https" && d.NetDialTLSContext != nil:
netDial = d.NetDialTLSContext
case d.NetDialContext != nil:
netDial = d.NetDialContext
case d.NetDial != nil:
netDial = func(ctx context.Context, net, addr string) (net.Conn, error) {
return d.NetDial(net, addr)
}
default:
netDial = (&net.Dialer{}).DialContext
}
that seems to indicate that NetDialTLSContext
is ONLY used if the scheme is https , but ignored otherwise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems we can remove this check or just shortcut and
if proxyURL.Scheme == "http" && d.NetDialTLSContext != nil { | |
return nil, errors.New("dial TLS function set for dialing non-HTTPS proxy") | |
} | |
if proxyURL.Scheme == "http" { | |
return proxyFromURL(proxyURL, netDial) | |
} |
if d.NetDialTLSContext != nil { | ||
netDial = d.NetDialTLSContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note for self:
- url is http and proxy-url is https, we replace the dialer ... users can specify a custom tls dialer just for the proxy.
- url is https and proxy-url is https, the same tls dialer is used for both
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- url is https and proxy-url is https, the same tls dialer is used for both
I do not think this is correct. There is only one "dial". It is either to the "proxy" or to the "upstream" server. If there is a proxy, the dial is to the "proxy" (and the TLS handshake must occur in the dial). The "proxy" server is the place that dials the "upstream" in this case. The second TLS handshake (not dial) to the "upstream" occurs over the previously established connection, and it MUST use the TLSClientConfig
. So the NetDialTLSContext
is only used for the proxy connection if it is set and the Proxy
function returns non-nil, HTTPS proxy URL.
@@ -29,7 +29,7 @@ func (fn netDialerFunc) DialContext(ctx context.Context, network, addr string) ( | |||
} | |||
|
|||
func proxyFromURL(proxyURL *url.URL, forwardDial netDialerFunc) (netDialerFunc, error) { | |||
if proxyURL.Scheme == "http" { | |||
if proxyURL.Scheme == "http" || proxyURL.Scheme == "https" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it there other possibility? doesn't this mean, we always use the httpProxyDialer
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes--This will always use the httpProxyDialer
. The difference is the forwardDial
, which now will also perform the TLS handshake if necessary.
The client is responsible for configuring the root CA certificates. The client TLS config contains a cert pool, which can contain multiple root CA certificates. So for TLS to the proxy and the upstream, the TLS config root CA cert pool must contain CA's which have signed both the proxy and the upstream. |
What type of PR is this? (check all applicable)
Description
Related Tickets & Documents
Added/updated tests?
Run verifications and test