@marcel91200 / caddy Mirror · read-only / commits / c82fe911
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 16:45 UTC

reverseproxy: Dynamic ServerName for TLS upstreams (#4836)

* Make reverse proxy TLS server name replaceable for SNI upstreams. * Reverted previous TLS server name replacement, and implemented thread safe version. * Move TLS servername replacement into it's own function * Moved SNI servername replacement into httptransport. * Solve issue when dynamic upstreams use wrong protocol upstream. * Revert previous commit. Old commit was: Solve issue when dynamic upstreams use wrong protocol upstream. Id: 3c9806ccb63e66bdcac8e1ed4520c9d135cb011d Co-authored-by: Matt Holt <mholt@users.noreply.github.com>

Kiss Károly Pál committed Jun 15, 2022 at 05:53 UTC c82fe91104efbbe62826510579ea57fd54c55f8c
1 file changed +39 -2
modules/caddyhttp/reverseproxy/httptransport.go
+39 -2
@@ -25,6 +25,7 @@ import (
25 "net/http"
26 "os"
27 "reflect"
28 + "strings"
29 "time"
30
31 "github.com/caddyserver/caddy/v2"
@@ -242,9 +243,45 @@ func (h *HTTPTransport) NewTransport(ctx caddy.Context) (*http.Transport, error)
243 return rt, nil
244 }
245
246 +// replaceTLSServername checks TLS servername to see if it needs replacing
247 +// if it does need replacing, it creates a new cloned HTTPTransport object to avoid any races
248 +// and does the replacing of the TLS servername on that and returns the new object
249 +// if no replacement is necessary it returns the original
250 +func (h *HTTPTransport) replaceTLSServername(repl *caddy.Replacer) *HTTPTransport {
251 + // check whether we have TLS and need to replace the servername in the TLSClientConfig
252 + if h.TLSEnabled() && strings.Contains(h.TLS.ServerName, "{") {
253 + // make a new h, "copy" the parts we don't need to touch, add a new *tls.Config and replace servername
254 + newtransport := &HTTPTransport{
255 + Resolver: h.Resolver,
256 + TLS: h.TLS,
257 + KeepAlive: h.KeepAlive,
258 + Compression: h.Compression,
259 + MaxConnsPerHost: h.MaxConnsPerHost,
260 + DialTimeout: h.DialTimeout,
261 + FallbackDelay: h.FallbackDelay,
262 + ResponseHeaderTimeout: h.ResponseHeaderTimeout,
263 + ExpectContinueTimeout: h.ExpectContinueTimeout,
264 + MaxResponseHeaderSize: h.MaxResponseHeaderSize,
265 + WriteBufferSize: h.WriteBufferSize,
266 + ReadBufferSize: h.ReadBufferSize,
267 + Versions: h.Versions,
268 + Transport: h.Transport.Clone(),
269 + h2cTransport: h.h2cTransport,
270 + }
271 + newtransport.Transport.TLSClientConfig.ServerName = repl.ReplaceAll(newtransport.Transport.TLSClientConfig.ServerName, "")
272 + return newtransport
273 + }
274 +
275 + return h
276 +}
277 +
278 // RoundTrip implements http.RoundTripper.
279 func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
247 - h.SetScheme(req)
280 + // Try to replace TLS servername if needed
281 + repl := req.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
282 + transport := h.replaceTLSServername(repl)
283 +
284 + transport.SetScheme(req)
285
286 // if H2C ("HTTP/2 over cleartext") is enabled and the upstream request is
287 // HTTP without TLS, use the alternate H2C-capable transport instead
@@ -252,7 +289,7 @@ func (h *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
289 return h.h2cTransport.RoundTrip(req)
290 }
291
255 - return h.Transport.RoundTrip(req)
292 + return transport.Transport.RoundTrip(req)
293 }
294
295 // SetScheme ensures that the outbound request req