diff --git a/docs/content/routing/entrypoints.md b/docs/content/routing/entrypoints.md index d13a6d77e..df8d9e676 100644 --- a/docs/content/routing/entrypoints.md +++ b/docs/content/routing/entrypoints.md @@ -128,7 +128,11 @@ entryPoints: ## ProxyProtocol -Traefik supports [ProxyProtocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt). +Traefik supports [ProxyProtocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2. + +If proxyprotocol header parsing is enabled for the entry point, this entry point can accept connections with or without proxyprotocol headers. + +If the proxyprotocol header is passed, then the version is determined automatically. ??? example "Enabling Proxy Protocol with Trusted IPs" diff --git a/go.mod b/go.mod index 9facb5675..9c15d4d14 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/VividCortex/gohistogram v1.0.0 // indirect github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 github.com/abronan/valkeyrie v0.0.0-20190802193736-ed4c4a229894 - github.com/armon/go-proxyproto v0.0.0-20190211145416-68259f75880e + github.com/c0va23/go-proxyprotocol v0.9.1 github.com/cenkalti/backoff/v3 v3.0.0 github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd diff --git a/go.sum b/go.sum index 798068511..cbaba2ca0 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,6 @@ github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/go-proxyproto v0.0.0-20190211145416-68259f75880e h1:h0gP0hBU6DsA5IQduhLWGOEfIUKzJS5hhXQBSgHuF/g= -github.com/armon/go-proxyproto v0.0.0-20190211145416-68259f75880e/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU= github.com/aws/aws-sdk-go v1.16.23/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.0 h1:ilfJN/vJtFo1XDFxB2YMBYGeOvGZl6Qow17oyD4+Z9A= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -80,6 +78,8 @@ github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/c0va23/go-proxyprotocol v0.9.1 h1:5BCkp0fDJOhzzH1lhjUgHhmZz9VvRMMif1U2D31hb34= +github.com/c0va23/go-proxyprotocol v0.9.1/go.mod h1:TNjUV+llvk8TvWJxlPYAeAYZgSzT/iicNr3nWBWX320= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4= @@ -203,6 +203,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= diff --git a/integration/proxy_protocol_test.go b/integration/proxy_protocol_test.go index 126aaf343..8533d9719 100644 --- a/integration/proxy_protocol_test.go +++ b/integration/proxy_protocol_test.go @@ -21,10 +21,11 @@ func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) { gatewayIP := s.composeProject.Container(c, "haproxy").NetworkSettings.Gateway haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress + file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct { HaproxyIP string WhoamiIP string - }{haproxyIP, whoamiIP}) + }{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP}) defer os.Remove(file) cmd, display := s.traefikCmd(withConfigFile(file)) @@ -33,18 +34,43 @@ func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - err = try.GetRequest("http://"+haproxyIP+"/whoami", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("X-Forwarded-For: "+gatewayIP)) - display(c) + err = try.GetRequest("http://"+haproxyIP+"/whoami", 500*time.Millisecond, + try.StatusCodeIs(http.StatusOK), + try.BodyContains("X-Forwarded-For: "+gatewayIP)) + c.Assert(err, checker.IsNil) +} + +func (s *ProxyProtocolSuite) TestProxyProtocolV2Trusted(c *check.C) { + gatewayIP := s.composeProject.Container(c, "haproxy").NetworkSettings.Gateway + haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress + whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress + + file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct { + HaproxyIP string + WhoamiIP string + }{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP}) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + err = try.GetRequest("http://"+haproxyIP+":81/whoami", 500*time.Millisecond, + try.StatusCodeIs(http.StatusOK), + try.BodyContains("X-Forwarded-For: "+gatewayIP)) c.Assert(err, checker.IsNil) } func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) { haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress + file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct { HaproxyIP string WhoamiIP string - }{haproxyIP, whoamiIP}) + }{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP}) defer os.Remove(file) cmd, display := s.traefikCmd(withConfigFile(file)) @@ -53,7 +79,30 @@ func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) { c.Assert(err, checker.IsNil) defer cmd.Process.Kill() - err = try.GetRequest("http://"+haproxyIP+"/whoami", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("X-Forwarded-For: "+haproxyIP)) - display(c) + err = try.GetRequest("http://"+haproxyIP+"/whoami", 500*time.Millisecond, + try.StatusCodeIs(http.StatusOK), + try.BodyContains("X-Forwarded-For: "+haproxyIP)) + c.Assert(err, checker.IsNil) +} + +func (s *ProxyProtocolSuite) TestProxyProtocolV2NotTrusted(c *check.C) { + haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress + whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress + + file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct { + HaproxyIP string + WhoamiIP string + }{HaproxyIP: haproxyIP, WhoamiIP: whoamiIP}) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + err = try.GetRequest("http://"+haproxyIP+":81/whoami", 500*time.Millisecond, + try.StatusCodeIs(http.StatusOK), + try.BodyContains("X-Forwarded-For: "+haproxyIP)) c.Assert(err, checker.IsNil) } diff --git a/integration/resources/haproxy/haproxy.cfg b/integration/resources/haproxy/haproxy.cfg index de649591c..b7330d9ba 100644 --- a/integration/resources/haproxy/haproxy.cfg +++ b/integration/resources/haproxy/haproxy.cfg @@ -16,6 +16,15 @@ frontend TestServerTest mode tcp default_backend TestServerNodes +frontend TestServerTestV2 + bind 0.0.0.0:81 + mode tcp + default_backend TestServerNodesV2 + backend TestServerNodes mode tcp - server TestServer01 172.17.0.1:8000 send-proxy \ No newline at end of file + server TestServer01 172.17.0.1:8000 send-proxy + + backend TestServerNodesV2 + mode tcp + server TestServer01 172.17.0.1:8000 send-proxy-v2 \ No newline at end of file diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index 4e890c91a..17dbc5c81 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/armon/go-proxyproto" + proxyprotocol "github.com/c0va23/go-proxyprotocol" "github.com/containous/traefik/v2/pkg/config/static" "github.com/containous/traefik/v2/pkg/ip" "github.com/containous/traefik/v2/pkg/log" @@ -240,10 +240,9 @@ func buildProxyProtocolListener(ctx context.Context, entryPoint *static.EntryPoi log.FromContext(ctx).Infof("Enabling ProxyProtocol for trusted IPs %v", entryPoint.ProxyProtocol.TrustedIPs) - return &proxyproto.Listener{ - Listener: listener, - SourceCheck: sourceCheck, - }, nil + return proxyprotocol.NewDefaultListener(listener). + WithSourceChecker(sourceCheck). + WithLogger(log.FromContext(ctx)), nil } func buildListener(ctx context.Context, entryPoint *static.EntryPoint) (net.Listener, error) {