Allow X-Forwarded-For delete operation

Co-authored-by: landrybe <lbenguigui@gmail.com>
This commit is contained in:
Romain 2023-09-22 11:00:07 +02:00 committed by GitHub
parent dbc679dc30
commit 4d63eb30f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 1 deletions

View file

@ -0,0 +1,31 @@
[global]
checkNewVersion = false
sendAnonymousUsage = false
[log]
level = "DEBUG"
[entryPoints]
[entryPoints.web]
address = ":8000"
[providers.file]
filename = "{{ .SelfFilename }}"
## dynamic configuration ##
[http.routers]
[http.routers.router1]
rule = "Host(`test.localhost`)"
middlewares = ["remove"]
service = "service1"
[http.middlewares]
[http.middlewares.remove.headers.customRequestHeaders]
X-Forwarded-For = ""
Foo = ""
[http.services]
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "http://127.0.0.1:9000"

View file

@ -1,7 +1,9 @@
package integration package integration
import ( import (
"net"
"net/http" "net/http"
"net/http/httptest"
"os" "os"
"time" "time"
@ -25,6 +27,46 @@ func (s *HeadersSuite) TestSimpleConfiguration(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
} }
func (s *HeadersSuite) TestReverseProxyHeaderRemoved(c *check.C) {
file := s.adaptFile(c, "fixtures/headers/remove_reverseproxy_headers.toml", struct{}{})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, found := r.Header["X-Forwarded-Host"]
c.Assert(found, checker.True)
_, found = r.Header["Foo"]
c.Assert(found, checker.False)
_, found = r.Header["X-Forwarded-For"]
c.Assert(found, checker.False)
})
listener, err := net.Listen("tcp", "127.0.0.1:9000")
c.Assert(err, checker.IsNil)
ts := &httptest.Server{
Listener: listener,
Config: &http.Server{Handler: handler},
}
ts.Start()
defer ts.Close()
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
req.Header = http.Header{
"Foo": {"bar"},
}
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}
func (s *HeadersSuite) TestCorsResponses(c *check.C) { func (s *HeadersSuite) TestCorsResponses(c *check.C) {
file := s.adaptFile(c, "fixtures/headers/cors.toml", struct{}{}) file := s.adaptFile(c, "fixtures/headers/cors.toml", struct{}{})
defer os.Remove(file) defer os.Remove(file)

View file

@ -10,6 +10,7 @@ import (
"github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/log"
"github.com/vulcand/oxy/v2/forward"
) )
// Header is a middleware that helps setup a few basic security features. // Header is a middleware that helps setup a few basic security features.
@ -70,6 +71,10 @@ func (s *Header) modifyCustomRequestHeaders(req *http.Request) {
// Loop through Custom request headers // Loop through Custom request headers
for header, value := range s.headers.CustomRequestHeaders { for header, value := range s.headers.CustomRequestHeaders {
switch { switch {
// Handling https://github.com/golang/go/commit/ecdbffd4ec68b509998792f120868fec319de59b.
case value == "" && header == forward.XForwardedFor:
req.Header[header] = nil
case value == "": case value == "":
req.Header.Del(header) req.Header.Del(header)

View file

@ -29,11 +29,14 @@ func TestNewHeader_customRequestHeader(t *testing.T) {
desc: "delete a header", desc: "delete a header",
cfg: dynamic.Headers{ cfg: dynamic.Headers{
CustomRequestHeaders: map[string]string{ CustomRequestHeaders: map[string]string{
"X-Forwarded-For": "",
"X-Custom-Request-Header": "", "X-Custom-Request-Header": "",
"Foo": "", "Foo": "",
}, },
}, },
expected: http.Header{}, expected: http.Header{
"X-Forwarded-For": nil,
},
}, },
{ {
desc: "override a header", desc: "override a header",