Skip to content

Commit

Permalink
proxy: ability to use client certs in reverse proxy (caddyserver#2914)
Browse files Browse the repository at this point in the history
* ability to use client certs in reverse proxy

* changed to http3.RoundTripper after review
  • Loading branch information
evtr authored and mholt committed Dec 4, 2019
1 parent 6f9a395 commit 5ec5033
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
20 changes: 20 additions & 0 deletions caddyhttp/proxy/reverseproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,26 @@ func (rp *ReverseProxy) UseOwnCACertificates(CaCertPool *x509.CertPool) {
}
}

// UseClientCertificates is used to facilitate HTTPS proxying
// with locally provided certificate.
func (rp *ReverseProxy) UseClientCertificates(keyPair *tls.Certificate) {
if transport, ok := rp.Transport.(*http.Transport); ok {
if transport.TLSClientConfig == nil {
transport.TLSClientConfig = &tls.Config{}
}
transport.TLSClientConfig.Certificates = []tls.Certificate{ *keyPair }
// No http2.ConfigureTransport() here.
// For now this is only added in places where
// an http.Transport is actually created.
} else if transport, ok := rp.Transport.(*http3.RoundTripper); ok {
if transport.TLSClientConfig == nil {
transport.TLSClientConfig = &tls.Config{}
}
transport.TLSClientConfig.Certificates = []tls.Certificate{ *keyPair }
}
}


// ServeHTTP serves the proxied request to the upstream by performing a roundtrip.
// It is designed to handle websocket connection upgrades as well.
func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request, respUpdateFn respUpdateFn) error {
Expand Down
19 changes: 19 additions & 0 deletions caddyhttp/proxy/upstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type staticUpstream struct {
CaCertPool *x509.CertPool
upstreamHeaderReplacements headerReplacements
downstreamHeaderReplacements headerReplacements
ClientKeyPair *tls.Certificate
}

type srvResolver interface {
Expand Down Expand Up @@ -267,6 +268,10 @@ func (u *staticUpstream) NewHost(host string) (*UpstreamHost, error) {
uh.ReverseProxy.UseOwnCACertificates(u.CaCertPool)
}

if u.ClientKeyPair != nil {
uh.ReverseProxy.UseClientCertificates(u.ClientKeyPair)
}

return uh, nil
}

Expand Down Expand Up @@ -564,6 +569,20 @@ func parseBlock(c *caddyfile.Dispenser, u *staticUpstream, hasSrv bool) error {
return c.Errf("unable to parse timeout duration '%s'", c.Val())
}
u.Timeout = dur
case "tls_client":
if !c.NextArg() {
return c.ArgErr()
}
clientCertFile := c.Val()
if !c.NextArg() {
return c.ArgErr()
}
clientKeyFile := c.Val()
clientKeyPair, err := tls.LoadX509KeyPair(clientCertFile, clientKeyFile)
if (err != nil) {
return c.Errf("unable to load keypair from certfile:%s keyfile:%s", clientCertFile, clientKeyFile)
}
u.ClientKeyPair = &clientKeyPair
default:
return c.Errf("unknown property '%s'", c.Val())
}
Expand Down

0 comments on commit 5ec5033

Please sign in to comment.