From f73f55dba745a8a527202b87fdd3ff88fa9f40b1 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Tue, 26 Oct 2021 16:41:28 -0400 Subject: reverseproxy: Sanitize scheme and host on incoming requests (#4237) * caddyhttp: Sanitize scheme and host on incoming requests * reverseproxy: Sanitize the URL scheme and host before proxying * Apply suggestions from code review Co-authored-by: Matt Holt Co-authored-by: Matt Holt --- modules/caddyhttp/reverseproxy/reverseproxy.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'modules') diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index e626962..36dfbfe 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -395,9 +395,23 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyht // should not permanently change r.Host; issue #3509) reqHost := r.Host reqHeader := r.Header + + // sanitize the request URL; we expect it to not contain the scheme and host + // since those should be determined by r.TLS and r.Host respectively, but + // some clients may include it in the request-line, which is technically + // valid in HTTP, but breaks reverseproxy behaviour, overriding how the + // dialer will behave. See #4237 for context. + origURLScheme := r.URL.Scheme + origURLHost := r.URL.Host + r.URL.Scheme = "" + r.URL.Host = "" + + // restore modifications to the request after we're done proxying defer func() { r.Host = reqHost // TODO: data race, see #4038 r.Header = reqHeader // TODO: data race, see #4038 + r.URL.Scheme = origURLScheme + r.URL.Host = origURLHost }() start := time.Now() -- cgit v1.2.3