Prevent traefik from forwarding client IP - traefik

I use traefik as a reverse reverse proxy for my Docker host. Additionally, I want to set up a static proxy to an external server. This is my current configuration:
defaultEntryPoints = ["http", "https"]
debug = false
logLevel = "ERROR"
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
compress = true
[entryPoints.https.tls]
[api]
[docker]
domain = "myhost.com"
watch = true
exposedByDefault = false
[file]
[backends]
[backends.otherhost]
[backends.otherhost.servers]
[backends.otherhost.servers.server0]
url = "http://otherhost.com"
[frontends]
[frontends.otherhost]
entryPoints = ["http", "https"]
backend = "otherhost"
[frontends.otherhost.routes]
[frontends.otherhost.routes.route0]
rule = "Host:subdomain.myhost.com"
[frontends.otherhost.headers.customRequestHeaders]
X-Forwarded-For = "foo"
X-Real-Ip = "foo"
Setting the headers to an empty string did nothing. With these settings, X-Real-Ip is foo but X-Forwarded-For becomes foo, <my real IP>. Can I prevent traefik from leaking the client IP to the external backend while still having it inside my Docker environment?

Traefik 2.x
What about using Middleware to override the X-Forwarded-For header. Documentation found here.
[http.middlewares]
[http.middlewares.testHeader.headers]
[http.middlewares.testHeader.headers.customRequestHeaders]
X-Forwarded-For = "foo"
[http.middlewares.testHeader.headers.customResponseHeaders]
X-Forwarded-For = "foo"
You can then apply specific middleware to your routers, like so:
[http.routers]
[http.routers.router1]
service = "myService"
middlewares = ["testHeader"]
rule = "Host(`example.com`)"
[http.middlewares]
[http.middlewares.testHeader.headers]
[http.middlewares.testHeader.headers.customRequestHeaders]
X-Forwarded-For = "foo"
[http.middlewares.testHeader.headers.customResponseHeaders]
X-Forwarded-For = "foo"
[http.services]
[http.services.service1]
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "http://127.0.0.1:80"
References:
Overview of Middleware - https://docs.traefik.io/v2.0/middlewares/overview/
Middwlare headers - https://docs.traefik.io/v2.0/middlewares/headers/

Related

Traefik 2.0 redirect

I would like to create a traefik v2 config file which redirects http://localhost:80 traffic to http://otherhost.example.com:8080.
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.dashboard]
address = ":80"
[entryPoints.dashboard.redirect???]
scheme = "http"
port = "8080"
No dockers whatsoever.
Thanks,
Lorand.
That worked:
defaultEntryPoints = ["http"]
## Static configuration
[entryPoints]
[entryPoints.web]
address = ":80"
[providers]
[providers.file]
filename = "dynamic_conf.toml"
watch = true
And dynamic_conf.toml:
## Dynamic configuration
[http.routers]
[http.routers.Router-1]
# By default, routers listen to every entry points
rule = "Host(`localhost`)"
service = "my-service"
[http.services]
[http.services.my-service.loadBalancer]
passHostHeader = false
[[http.services.my-service.loadBalancer.servers]]
url = "http://example.com"
It had to be called with full url, like: http://localhost/index.html

Redirect Multiple Domains to external URLs in Traefik

After reading the github issues related to this with a bunch of loose snippets, It's still completely unclear how to write simple 301 redirects in Traefik as I used to do in nginx like this:
server_name foo.com
return 301 https://bar.com
The plan is: redirect any request in http-scheme to https (same domain), regardless whether the domain exists or not like in nginx default host on port 80 with redirect 301 https://$host.
Then, matching the https-Host, return a redirect code with the new Location: - Header.
My base traefik.toml is:
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
minVersion = "VersionTLS12"
[acme]
email = "acme#mydomain.com"
storage = "/etc/traefik/acme/acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[file]
directory = "/etc/traefik/conf/"
watch = true
Now, how does a file in conf/ must look like to adopt the above nginx redirect? It's about ~300 domains which are hosted at another place, so no backend needed, and it must not be 302/rewrites to be SEO-conform.
This pr https://github.com/containous/traefik/pull/2570 seems to be near to what I want, but there's no documentation how to use it.

Traefik frontend redirects doesn't work

Hey i am trying catch all request to an Subdomain, with no matching rool and redirect them to https://localhost:8000 without subdomain and suburl. But there is no redirect, i just get the response from the backend.
[file]
[frontends]
[frontends.homeRedirect]
entryPoints = ["https"]
priority = 1
backend = "homeRedirect"
[frontends.homeRedirect.routes.everything]
rule = "PathPrefix:/"
[frontends.homeRedirect.headers]
SSLRedirect = true
[frontends.homeRedirect.redirect]
regex = "(.*)"
replacement = "https://localhost:8000"
[backends]
[backends.homeRedirect]
[backends.homeRedirect.servers]
[backends.homeRedirect.servers.server0]
url = "http://frontend:80"
Is there something wrong with my file?
In this case, a redirect on the entry point is more appropriate:
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
regex = "^http://subdomain.mydomain/(.*)"
replacement = "http://myotherdomain/$1"
https://docs.traefik.io/v1.5/configuration/entrypoints/#rewriting-url
localhost inside the Traefik container is the container not the real machine.

Is HTTP to HTTPS redirection configurable per frontend in the Træfik File backend?

According to https://github.com/containous/traefik/pull/2133, it should be possible to redirect selectively per frontend. Is this available in the File backend?
I tried adding the following, but it didn't work:
[frontends.foo.headers]
SSLRedirect = true
The option SSLRedirect = true always redirect on 443.
If you want to redirect to an entry point without using 443 port use entryPoint = "https"
https://docs.traefik.io/user-guide/examples/#http-redirect-on-https
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "examples/traefik.crt"
keyFile = "examples/traefik.key"
https://docs.traefik.io/configuration/backends/file/
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
# ...
[entryPoints.https]
address = ":443"
# ...
[file]
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.redirect]
entryPoint = "https"
# ...

Traeffik does not map incoming 443 to port 80 internally

Our problem is that traffic from the https entrypoint is (probably) forwarded to the backend with the wrong port. Accessing the http entrypoint works as expected: the traffic is loadbalanced between server 1 2 3. when using the https entrypoint, we get a 404 page not found. The TLS is all good, the connection is secure, but it looks like traefik does not change the port for the backend server to :80.
We do let's encrypt via traefik and this looks good.
Here's how we start traffic:
docker run -d -p 443:443 -p 80:80 -v /home/pi/lbtest/traefik/traefik.toml:/traefik.toml -v /home/pi/lbtest/traefik/acme.json:/acme.json traefik
And this is our traefik.toml
debug = true
[file]
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[frontends]
[frontends.lbtest]
backend = "lbtest"
[frontends.lbtest.routes.route0]
rule = "Host:xxx.gotdns.ch"
[backends]
[backends.lbtest]
[backends.lbtest.servers.server1]
url = "http://192.168.178.81:80"
[backends.lbtest.servers.server2]
url = "http://192.168.178.49:80"
[backends.lbtest.servers.server3]
url= "http://192.168.178.64:80"
[acme]
email = "xxx#xxx.eu.com"
storageFile = "acme.json"
acmeLogging = true
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[[acme.domains]]
main = "xxx.gotdns.ch"
Why does http://xxx.gotdns.ch work - it loadbalances between server 1 2 3 - but not for https://xxx.gotdns.ch. Any ideas?
It's problem with the field defaultEntryPoints in your configuration:
debug = true
defaultEntryPoints = ["http", "https"] # <-- move the field here
[file]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[frontends]
[frontends.lbtest]
backend = "lbtest"
[frontends.lbtest.routes.route0]
rule = "Host:xxx.gotdns.ch"
[backends]
[backends.lbtest]
[backends.lbtest.servers.server1]
url = "http://192.168.178.81:80"
[backends.lbtest.servers.server2]
url = "http://192.168.178.49:80"
[backends.lbtest.servers.server3]
url= "http://192.168.178.64:80"
[acme]
email = "xxx#xxx.eu.com"
storageFile = "acme.json"
acmeLogging = true
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[[acme.domains]]
main = "xxx.gotdns.ch"
I recommend to write your configuration like that:
debug = true
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "xxx#xxx.eu.com"
storageFile = "acme.json"
acmeLogging = true
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[[acme.domains]]
main = "xxx.gotdns.ch"
[file]
[frontends]
[frontends.lbtest]
backend = "lbtest"
[frontends.lbtest.routes.route0]
rule = "Host:xxx.gotdns.ch"
[backends]
[backends.lbtest]
[backends.lbtest.servers.server1]
url = "http://192.168.178.81:80"
[backends.lbtest.servers.server2]
url = "http://192.168.178.49:80"
[backends.lbtest.servers.server3]
url= "http://192.168.178.64:80"