I am implementing Traefik, I come from Apache.
I have a problem, I have several rest services that communicate with each other. When I make a request to a service, I pass it a header that contains the bearer token and it passes it to a service that validates the token.
I have this tag for java backend:
"traefik.http.services.servicename.loadbalancer.server.port=8080"
The problem comes when I make the request https://url/path
This tells me that it cannot reach the container that validates through port 80.
If I make the request indicating https://url:443/path
It returns that it cannot find the validator on port 443.
And if I map port 8080 in Trafik and make the request to http://url:8080/path , it makes the request correctly against the validator.
I think the proxypass reverse is not working well,
Can you help me?
Thank you
Share your full Traefik static and dynamic config, and docker-compose.yml
if used.
Check simple Traefik Swarm example .
My dinamic conf is:
version: '3.2'
services:
traefik:
image: traefik:v2.10.0
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
- target: 8080
published: 8080
mode: host
command:
- --api.debug=false
- --providers.docker=true
- --providers.docker.exposedByDefault=false
- --providers.docker.useBindPortIP=false
- --providers.docker.network=traefik
- --providers.docker.swarmMode=true
- --providers.docker.swarmModeRefreshSeconds=10
- --entrypoints.web.address=:80
- --entrypoints.internal.address=:8080
- --entrypoints.websecure.address=:443
- --providers.file.filename=/etc/traefik/tls.yml
#- --log.level=DEBUG
#- --accesslog=true
- --api
- --api.dashboard=true
#- --api.insecure=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/ssl/letsencrypt:/certificates
- /datos/traefik/conf/tls.yml:/etc/traefik/tls.yml
networks:
- traefik
deploy:
mode: global
placement:
constraints: [node.role==manager]
labels:
- "traefik.enable=true"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
#web-dashboard
- "traefik.http.routers.dashboard.rule=Host(traefik.adrian.es
)"
- "traefik.http.routers.dashboard.service=dashboard@internal"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.middlewares=traefik-auth"
- "traefik.http.routers.dashboard.tls.domains[0].main=traefik.adrian.es"
- "traefik.http.routers.dashboard.tls.domains[0].sans=traefik.adrian.es"
#api
- "traefik.http.routers.api.rule=Host(traefik.adrian.es
) && PathPrefix(/api
)"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.domains[0].main=traefik.adrian.es"
- "traefik.http.routers.api.tls.domains[0].sans=traefik.adrian.es"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$6ifcgj3l$$OY0WwCX2UDA7/Agxv.chV/"
#hsts
- "traefik.http.middlewares.comunssl.headers.stsSeconds=15552000"
- "traefik.http.middlewares.comunssl.headers.stsIncludeSubdomains=true"
- "traefik.http.middlewares.comunssl.headers.stsPreload=true"
#cors
- "traefik.http.middlewares.comunssl.headers.customResponseHeaders.Access-Control-Allow-Origin=*"
#upgrade insecure request
- "traefik.http.middlewares.comunssl.headers.customResponseHeaders.Content-Security-Policy=upgrade-insecure-requests"
#Redirect
- "traefik.http.middlewares.comunssl.headers.sslRedirect=true"
- "traefik.http.middlewares.redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect.redirectscheme.permanent=true"
#is development?
- "traefik.http.middlewares.dev.headers.isDevelopment=true"
networks:
traefik:
external: true
In the tls.yml it only defines the ssl certificates
Please use 3 backticks in front and after code to make it readable, in yaml every space matters.
Check and compare to simple Traefik Swarm example .
Sorry is a bug to copy/paste code. in real code I have backticks
the code well copied its:
version: '3.2'
services:
traefik:
image: traefik:v2.10.0
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
- target: 8080
published: 8080
mode: host
command:
- --api.debug=false
- --providers.docker=true
- --providers.docker.exposedByDefault=false
- --providers.docker.useBindPortIP=false
- --providers.docker.network=traefik
- --providers.docker.swarmMode=true
- --providers.docker.swarmModeRefreshSeconds=10
- --entrypoints.web.address=:80
- --entrypoints.internal.address=:8080
- --entrypoints.websecure.address=:443
- --providers.file.filename=/etc/traefik/tls.yml
- --api
- --api.dashboard=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/ssl/letsencrypt:/certificates
- /datos/traefik/conf/tls.yml:/etc/traefik/tls.yml
networks:
- traefik
deploy:
mode: global
placement:
constraints: [node.role==manager]
labels:
- traefik.enable=true
- traefik.http.services.traefik.loadbalancer.server.port=8080
- traefik.http.routers.dashboard.rule=Host(`traefik.adrian.es`)
- traefik.http.routers.dashboard.service=dashboard@internal
- traefik.http.routers.dashboard.entrypoints=websecure
- traefik.http.routers.dashboard.middlewares=traefik-auth
- traefik.http.routers.dashboard.tls.domains[0].main=traefik.adrian.es
- traefik.http.routers.dashboard.tls.domains[0].sans=traefik.adrian.es
- traefik.http.routers.api.rule=Host(`traefik.adrian.es`) && PathPrefix(`/api`)
- traefik.http.routers.api.service=api@internal
- traefik.http.routers.api.entrypoints=websecure
- traefik.http.routers.api.tls.domains[0].main=traefik.adrian.es
- traefik.http.routers.api.tls.domains[0].sans=traefik.adrian.es
- traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$6ifcgj3l$$OY0WwCX2UDA7/Agxv.chV/
- traefik.http.middlewares.comunssl.headers.stsSeconds=15552000
- traefik.http.middlewares.comunssl.headers.stsIncludeSubdomains=true
- traefik.http.middlewares.comunssl.headers.stsPreload=true
- traefik.http.middlewares.comunssl.headers.customResponseHeaders.Access-Control-Allow-Origin=*
- traefik.http.middlewares.comunssl.headers.customResponseHeaders.Content-Security-Policy=upgrade-insecure-requests
- traefik.http.middlewares.comunssl.headers.sslRedirect=true
- traefik.http.middlewares.redirect.redirectscheme.scheme=https
- traefik.http.middlewares.redirect.redirectscheme.permanent=true
- traefik.http.middlewares.dev.headers.isDevelopment=true
networks:
traefik:
external: true
have space matters and work but when i request the url and this request in internal net to other container change the port
Not sure if you see it, but for me there is no spacing in your posted config.
Now better? I formatted the text
The problem seems to be that in Apache Reverse Proxy replaces the port with that of ProxyPassReverse and in Trafik it does not replace it, it maintains the default one.
Any solution without touching the application code?
Can you share the config for your target service?
Yes, this is a compose of 2 rest service, the problem is that pmovil request to arq with auth token in internal net. pmovil ping to arq but the request its forbidden because pmovil send it port 80.
If I change my request to http://drservices.adrian.es:8080/pmovil , pmovil send request to http://arqserver:8080 and arq answer correctly.
And if I change request to https://drservices.adrian.es:443/pmovil , pmovil send request to https://arqserver:443 and dont connect
version: '3.7'
services:
arq:
image: "pruebaarq"
networks:
traefik:
aliases:
- arqserver
ServiciosRest-New:
aliases:
- arqserver
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.hostname == cdocker1]
labels:
- traefik.enable=true
- traefik.http.routers.arqserver.rule=Host(`drservices.adrian.es`) && PathPrefix(`/arq`)
- traefik.http.services.arqserver.loadbalancer.server.port=8080
- traefik.http.routers.arqserver.middlewares=comunssl,redirect
- traefik.http.routers.arqserver.entrypoints=websecure
- traefik.http.routers.arqserver.tls=true
- traefik.http.routers.arqserver.tls.domains[0].main=drservices.adrian.es
- traefik.http.routers.arqserver.tls.domains[0].sans=drservices.adrian.es
pmovil:
image: "pruebapmovil"
networks:
traefik:
aliases:
- pmovilserver
ServiciosRest-New:
aliases:
- pmovilserver
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.hostname == cdocker1]
labels:
- traefik.enable=true
- traefik.http.routers.pmovilservice.rule=Host(`drservices.adrian.es`) && PathPrefix(`/pmovil`)
- traefik.http.routers.pmovilservice.entrypoints=internal
- traefik.http.routers.pmovilserver.rule=Host(`drservices.adrian.es`) && PathPrefix(`/pmovil`)
- traefik.http.services.pmovilserver.loadbalancer.server.port=8080
- traefik.http.routers.pmovilserver.middlewares=comunssl,redirect
- traefik.http.routers.pmovilserver.entrypoints=websecure
- traefik.http.routers.pmovilserver.tls=true
- traefik.http.routers.pmovilserver.tls.domains[0].main=drservices.adrian.es
- traefik.http.routers.pmovilserver.tls.domains[0].sans=drservices.adrian.es
networks:
traefik:
external: true
ServiciosRest-New:
external: true
Thank you for your time.
Have you enabled and checked Traefik dashboard and Traefik debug log?
You should have loaded your custom certs with matching CNAMEs via tls.yml
, then you can use traefik.http.routers.arqserver.tls=true
.
If you want to use LetsEncrypt, then you need to create and assign a certresolver, see simple Traefik example .
This is not needed, as Traefik reads hostname from Host()
:
- traefik.http.routers.arqserver.tls.domains[0].main=drservices.adrian.es
- traefik.http.routers.arqserver.tls.domains[0].sans=drservices.adrian.es
It’s usually only used when SANS is a wildcard.
Notes on Docker Swarm:
Traefik CE is not able to handle distributed LE, as in LE on multiple Traefik nodes.
When using custom certs, you need to make sure they are available on all Traefik-running nodes.
I have static buyed certificates, i can't letsEncrypt.
But this isn't problem.
The Rest Services get the port with request.gerServerPort().
In apache set port of "ProxyPassReverse http://ipdocker:8080/arq "
But traefik when get request.gerServerPort() set port 80, don't pass the port 8080
I don’t understand where Apache is coming into play here.
Even inside a container you should be able to do a request to https port 443 for Traefik to receive the request, terminate TLS (decrypt), and forward it to the target service with http to the loadbalancer.server.port
of the service.
I have it working right now with Apache that way.
I'm migrating it to Traefik and Docker Swarm.
The requests that I make to the rest services through the loadbalancer, to https://drservices.adrian.es/pmovil and https://drservices.adrian.es/arq work correctly.
What does not work is when, through a request to https://drservices.adrian.es/pmovil/verifica , it internally makes a request to http://arqserver/validate .
And I include the port with what I capture from request.getServerPort() in Spring (8080).
With Apache and nginx it works correctly, and now when migrating to Traefik it gives me the error that request.getServerPort() is giving me port 80
Which service is using that? The first one?
yes, pmovil use request.getServerPort() to set port in internal comunication to arqserver
Why would you make request 2 port dependent on request 1 port?
You need to decide if you want to use only the Docker network for the internal request, then it should probably be http://arq:8080
.
Client -> https:443 -> Traefik -> http:8080 -> pmovil -> http:8080 -> arq
But you created a Traefik router for arq, then the request should probably be https://fqdn:443
.
It should probably not be http://fqdn(:80)
, because then you have the service available externally without TLS.
Thanks, but I already found the solution, with the option:
traefik.http.services.arqserver.loadBalancer.passHostHeader=false
Traefik was passing the headers with the port and that is why it replaced
system
Closed
December 2, 2023, 7:02am
20
This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.