I want to configure traefik to forward a request to another host, but instead of setting X-Forwarded-Host to host.name I want it to set the header filed Host to host.name but still opening the connection to my.ip
This is the part of my current traefik toml.
[frontends]
[frontends.mypath]
backend = "backendhost"
passHostHeader = true
[frontends.mypath.routes.test]
rule = "Host:host.name;Path:/my/path/"
[backends]
[backends.backendhost]
[backends.backendhost.servers.myip]
url = "http://my.ip:80"
basically I want traefik to behave in the way as I can do it with curl:
curl -L -H "Host: host.name" http://my.ip/my/path
so the requested server thinks it is requested as http://host.name/my/path.
The answer needs to be applicable directly to the traefik configuration. It should not include using further services/containers/reverse proxies.
The in addition to X-Forwarded-Host will look like this:
[frontends]
[frontends.mypath]
backend = "backendhost"
[frontends.mypath.headers.customrequestheaders]
Host = "host.name"
[frontends.mypath.routes.test]
rule = "Host:host.name;Path:/my/path/"
[backends]
[backends.backendhost]
[backends.backendhost.servers.myip]
url = "http://my.ip:80"
Related
Traefik 1.7
Docker
Spring Boot
I need to use the auth forwarding capabilities of Traefik.
My auth endpoint is exposed by a spring boot component behind the Traefik and exposed as "backend-authentication" with URI "http://123.1.23.5:8081" in Traefik Dashboard.
In my configuration, traefik routes everything from "http://api-dev.mycompany.com" to backends API using "PathPrefix" rules.
Therefore my authentication component is available as "http://api-dev.mycompany.com/authentication"
When I do auth forwarding like this:
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.auth.forward]
address = "http://api-dev.mycompany.com/commerce/authentication/v1/ldap/auth"
trustForwardHeader = true
authResponseHeaders = ["Authorization"]
Traefik goes through endless forwarding loop.
When I use the following configuration it is working as wanted:
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.auth.forward]
address = "http://123.1.23.5:8081/commerce/authentication/v1/ldap/auth"
trustForwardHeader = true
authResponseHeaders = ["Authorization"]
I would like to use a service name related to the backend-authentication as seen in Traefik dashboard but when I try that configuration:
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.auth.forward]
address = "http://backend-authentication/commerce/authentication/v1/ldap/auth"
trustForwardHeader = true
authResponseHeaders = ["Authorization"]
I ran into error 500.
I do need the capability to use logic name and not IP as there are subject to change.
I cannot run the component on another port or another network... Any idea would be apreciated.
Maybe you could upgrade to v2, it's a bit more clear there:
In Traefik v2 according to the docs you have to use forwardAuth as a middleware. You have to create a router like this:
## Dynamic configuration
[http.routers]
[http.routers.my-router] <-- name it auth-router or whatever
rule = "Path(`/foo`)"
# declared in next code block
middlewares = ["test-auth"]
service = "youre-service-docker-or-file" <-- probably your "backend-authentication"
Where your middleware is:
# Forward authentication to authserver.com
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth" <--- Your auth server here
Optionally, looking at the v1.7 docs, can you set
authResponseHeaders = ["X-Auth-User", "X-Secret"]
below the entrypoints, and maybe try add some trusted ips:
[entryPoints]
[entryPoints.http]
address = ":80"
# Enable Forwarded Headers
[entryPoints.http.forwardedHeaders]
# List of trusted IPs
#
# Required
# Default: []
#
trustedIPs = ["127.0.0.1/32", "192.168.1.7"]
I have read the documentation but I can not figure out how to configure Traefik v2 to replace Nginx as a reverse proxy for web sites (virtual hosts) without involving Docker. Ideally there would be let'sencrypt https as well.
I have a service running at http://127.0.0.1:4000 which I would like to reverse proxy to from http://myhost.com:80
This is the configuration i've come up with so far:
[Global]
checkNewVersion = true
[log]
level = "DEBUG"
filePath = "log-file.log"
[accessLog]
filePath = "log-access.log"
bufferingSize = 100
[entrypoints]
[entrypoints.http]
address = ":80"
[http]
[http.routers]
[http.routers.my-router]
rule = "Host(`www.myhost.com`)"
service = "http"
entrypoint=["http"]
[http.services]
[http.services.http.loadbalancer]
[[http.services.http.loadbalancer.servers]]
url = "http://127.0.0.1:4000"
I figured it out,
the first part to note is that in traefik v2 there are two types of configuration, static and dynamic. So I created two files, traefik.toml and traefik-dynamic.toml.
contents of traefik.toml:
[log]
level = "DEBUG"
filePath = "log-file.log"
[accessLog]
filePath = "log-access.log"
bufferingSize = 100
[providers]
[providers.file]
filename = "traefik-dynamic.toml"
[api]
dashboard = true
debug = true
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web-secure]
address = ":443"
[entryPoints.dashboard]
address = ":8080"
[certificatesResolvers.sample.acme]
email = "myemail#example.com"
storage = "acme.json"
[certificatesResolvers.sample.acme.httpChallenge]
# used during the challenge
entryPoint = "web"
traefik-dynamic.toml:
[http]
# Redirect to https
[http.middlewares]
[http.middlewares.test-redirectscheme.redirectScheme]
scheme = "https"
[http.routers]
[http.routers.my-router]
rule = "Host(`www.example.com`)"
service = "phx"
entryPoints = ["web-secure"]
[http.routers.my-router.tls]
certResolver = "sample"
[http.services]
[http.services.phx.loadbalancer]
[[http.services.phx.loadbalancer.servers]]
url = "http://127.0.0.1:4000"
You can also use Traefik v2 to reverse proxy to a service running on the localhost without using Nginx as explained here using File (and not Docker provider) for Traefik.
First, route calls to myhost.com through localhost by updating /etc/hosts like:
127.0.0.1 myhost.com
Create a minimal docker-compose.yml like:
version: "3.7"
services:
proxy:
image: traefik:2.0
command:
- "--providers.file.filename=/etc/traefik/proxy-config.toml"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
- ./proxy-config.toml:/etc/traefik/proxy-config.toml:ro
This Compose file creates a read-only volume containing the dynamic configuration for the Traefik reverse proxy standing in for Nginx as requested. It uses the File provider for Traefik and not Docker and a blank HTTP address mapped to port 80 for the entrypoint. This is a complete Compose file in itself. Beyond that all that's needed is the reverse proxy configuration for Traefik.
Configure the Traefik reverse proxy proxy-config.toml in the same directory:
[http.routers.test-streamrouter]
rule = "Host(`myhost.com`)"
service = "test-loadbalancer"
entryPoints = ["web"]
[[http.services.test-loadbalancer.loadBalancer.servers]]
url = "http://host.docker.internal:4000"
This is a sample reverse proxy in its entirety. It can be enhanced with middlewares to perform URL rewriting, update domain names or even redirect users if that's your aim. A single load balancer is used as shown in this answer. And host.docker.internal is used to return the host's internal networking address.
Note: At time of writing "host.docker.internal" only works with Docker for Mac and will fail on Linux. However, you may be able to use the Compose service name instead (i.e. "proxy").
Once you get this working you can set up the Let's Encrypt stuff or swap between development and production configurations using the TRAEFIK_PROVIDERS_FILE_FILENAME environment variable.
You can
use container names within the same bridged network instead of localhost
link middlewares and services without #file suffix
Please mind, that in the yaml and toml file, you need to pay attention to lower-uppercase of the properties. Whereas in docker it is loadbalancer, you need to write loadBalencer in the config file.
http:
middlewares:
docs:
stripPrefix:
prefixes:
- "/docs"
restapi:
stripPrefix:
prefixes:
- "/api/v1"
routers:
restapi:
rule: "PathPrefix(`/api/v1`)"
middlewares:
- "restapi"
service: "restapi"
entryPoints:
- http
docs:
rule: "PathPrefix(`/docs`)"
middlewares:
- "docs"
service: "docs"
entryPoints:
- http
client:
rule: "PathPrefix(`/`)"
service: "client"
entryPoints:
- http
help:
rule: "PathPrefix(`/server/sicon/help`)"
services:
restapi:
loadBalancer:
servers:
- url: "http://sicon_backend:1881"
docs:
loadBalancer:
servers:
- url: "http://sicon_backend:1882"
client:
loadBalancer:
servers:
- url: "http://sicon_client"
I have a very simple definition in traefik.toml file. The backend is a service that echoes back the header passed through.
[frontends]
[frontends.test]
entryPoints = ["http"]
backend = "test"
passHostHeader = true
[frontends.test.routes]
[frontends.test.routes.route0]
rule = "Host:localhost;PathPrefixStrip:/test"
[backends]
[backends.test]
[backends.test.servers]
[backends.test.servers.server0]
url = "http://localhost:8000"
weight = 1
I can pass any http header from the client to the backend and it is echoed back as implemented in the backend service. However I cannot pass soapaction header. Traefik does not return any response till it times out. Nothing in the log that indicates an issue.
Any help will be much appreciated
This may be due to the fact that Traefik rewrites headers canonically as they should be case-insensitive (see https://github.com/containous/traefik/issues/466).
Could you check that on your backend server ?
I have a set of IBM Websphere Liberty profiles servers inside a HAProxy reverse proxy. Everything works ok but HAProxy is doing something on requests so I can't get the correct URL in the requests using uriInfo.getBaseUri() or uriInfo.getRequestUriBuilder().build("whatever path")... they both return localhost:9080 as host and port, so I can't build correct URLs pointing to the service. (The request is a standard http://api.MYHOST.com/v1/... REST request )
Of course, I get a uriInfo object using #Context in the method so it gets the request information.
Front end configuration:
reqadd X-Forwarded-Proto:\ http
# Add CORS headers when Origin header is present
capture request header origin len 128
http-response add-header Access-Control-Allow-Origin %[capture.req.hdr(0)] if { capture.req.hdr(0) -m found }
rspadd Access-Control-Allow-Methods:\ GET,\ HEAD,\ OPTIONS,\ POST,\ PUT if { capture.req.hdr(0) -m found }
rspadd Access-Control-Allow-Credentials:\ true if { capture.req.hdr(0) -m found }
rspadd Access-Control-Allow-Headers:\ Origin,\ X-Requested-With,\ Content-Type,\ Accept if { capture.req.hdr(0) -m found }
And Back-end configuration is:
option forwardfor
http-request set-header Host api.MYHOST.com
http-request set-header X-Forwarded-Host %[dst]
http-request set-header X-Forwarded-Port %[dst_port]
Any ideas on how to get the real request?
The only way I managed to get correct host used in the request is injecting in the method parameters the HttpServletRequest object.
I also inject the UriInfo, which has all valid information except the host name:
#Context UriInfo uriInfo, #Context HttpServletRequest request
After that I use URIBuilder (not UriBuilder) from Apache HttpClient utils to change the Host to the correct one as jax-rs UriBuilder in immutable:
new URIBuilder(uriInfo.getBaseUriBuilder().path("/MyPath").queryParam("MyParameter",myParameterValue)).build()).setHost(request.getServerName()).toString()
I also had to include setPort() and setScheme() to make sure the correct port and scheme are used (the correct ones are in HttpServletRequest, not UriInfo)
I just faced this very issue on my Jersey based application, I used uriInfo.getBaseUriBuilder() to get a UrlBuilder and figured out that it's possible to change the hostname from localhost by using the .host() method
.host(InetAddress.getLocalHost().getHostName())
And you can remove the port part by setting it to -1
.port(-1)
So from a URL that looks like
https://127.0.0.1:8443/hello
I got
https://yourhostname/hello
Using HAProxy v1.6
I'm doing Websocket request that currently (at least on javascript) won't support custom headers.
I'm trying to add a custom header at the HAProxy layer (before forwarding it to the load balancer) based on a get parameter
Example:
The next code works (on backend)
#match get-url someGetKey paramater
acl is_key_match url_reg \?(?:.*?)someGetKey=([\w|=]+)
#Add header
http-request set-header My-Custom-Header hardcoded_string if is_key_match
My goal is the to replace hardcoded_string with the first match group of the regex \?(?:.*?)someGetKey=([\w|=]+)
Is it possible?
Thanks!
Found the solution:
http-request set-header cookie %[urlp(SSession)] if is_sticky_url
%[] - variable
url(SSession) - HTTP-GET parameter with the key SSession
For that example, the URL:
https://www.example.com/path?sSession=abcd
will forward a request with the header:
cookie=abcd