From f476eddbb05a86b85c4aa7b3b87ace8a46153b42 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Mon, 18 Sep 2023 20:21:41 +0100 Subject: [PATCH] Fix duplicate entry for `X-Forwarded-For` header (#32039) * Fix duplicate entry for `X-Forwarded-For` header PR #27761 replaced `oxy.Forwarder` with `httputil.ReverseProxy`. The new forwarder based on `httputil.ReverseProxy` is appending the `X-Forwarder-For` header values instead of replacing them. This PR fixes that behavior and forces the XFF header to be a single value. Signed-off-by: Tiago Silva * Update lib/httplib/reverseproxy/rewriter_test.go Co-authored-by: Reed Loden --------- Signed-off-by: Tiago Silva Co-authored-by: Reed Loden --- lib/httplib/reverseproxy/rewriter.go | 12 ++++++++---- lib/httplib/reverseproxy/rewriter_test.go | 9 ++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/httplib/reverseproxy/rewriter.go b/lib/httplib/reverseproxy/rewriter.go index 807ce421b77..03a644768a7 100644 --- a/lib/httplib/reverseproxy/rewriter.go +++ b/lib/httplib/reverseproxy/rewriter.go @@ -54,8 +54,8 @@ func (rw *HeaderRewriter) Rewrite(req *http.Request) { // Set X-Real-IP header if it is not set to the IP address of the client making the request. maybeSetXRealIP(req) - // Set X-Forwarded-Proto header if it is not set to the scheme of the request. - maybeSetForwardedProto(req) + // Set X-Forwarded-* headers if it is not set to the scheme of the request. + maybeSetForwarded(req) if xfPort := req.Header.Get(XForwardedPort); xfPort == "" { req.Header.Set(XForwardedPort, forwardedPort(req)) @@ -104,9 +104,13 @@ func maybeSetXRealIP(req *http.Request) { } } -// maybeSetForwardedProto sets X-Forwarded-Proto header if it is not set to the +// maybeSetForwarded sets X-Forwarded-* headers if it is not set to the // scheme of the request. -func maybeSetForwardedProto(req *http.Request) { +func maybeSetForwarded(req *http.Request) { + // We need to delete the value because httputil.ReverseProxy + // appends to the existing value. + req.Header.Del(XForwardedFor) + if req.Header.Get(XForwardedProto) != "" { return } diff --git a/lib/httplib/reverseproxy/rewriter_test.go b/lib/httplib/reverseproxy/rewriter_test.go index 31913c52755..e4c960c8fe5 100644 --- a/lib/httplib/reverseproxy/rewriter_test.go +++ b/lib/httplib/reverseproxy/rewriter_test.go @@ -89,8 +89,10 @@ func TestRewriter(t *testing.T) { expected http.Header }{ { - desc: "set x-real-ip", - reqHeaders: http.Header{}, + desc: "set x-real-ip", + reqHeaders: http.Header{ + XForwardedFor: []string{"1.2.3.4"}, + }, tlsReq: true, hostReq: "teleport.dev:3543", remoteAddr: "1.2.3.4:1234", @@ -105,7 +107,8 @@ func TestRewriter(t *testing.T) { { desc: "trust x-real-ip", reqHeaders: http.Header{ - XRealIP: []string{"5.6.7.8"}, + XRealIP: []string{"5.6.7.8"}, + XForwardedFor: []string{"1.2.3.4"}, }, tlsReq: false, hostReq: "teleport.dev:3543",