When using Traefik and Docker-compose, I would like to get the container IP to perform IP-based filtering but instead get the docker network gateway IP.
Here is the results of a curl request from the curl-client container:
docker-compose exec curl-client curl https://whoami.domain.name
Hostname: 608f3dcaf7d9
IP: 127.0.0.1
IP: 172.18.0.2
GET / HTTP/1.1
Host: whoami.domain.name
User-Agent: curl/7.58.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.18.0.1
X-Forwarded-Host: whoami.domain.name
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 88756553599b
X-Real-Ip: 172.18.0.1
Here, 172.18.0.1 is the gateway for the traefik_net network. Instead, I would expect to see 172.18.0.9 in the X-Forwarded-For field, as it is the IP of the curl-client container:
docker-compose exec curl-client cat /etc/hosts
172.18.0.9 34f7b6e5472f
I've also tried using the 'traefik.frontend.whiteList.useXForwardedFor=true' option without success.
traefik.toml
logLevel = "ERROR"
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.dashboard]
address = ":8080"
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[api]
entrypoint="dashboard"
[acme]
email = "something@aaa.com"
storage = "acme.json"
entryPoint = "https"
[acme.dnsChallenge]
provider = "ovh"
delayBeforeCheck = 0
[[acme.domains]]
main = "*.domain.name"
[docker]
domain = "domain.name"
watch = true
network = "traefik_net"
docker-compose.yml
version: '3'
services:
traefik_proxy:
image: traefik:alpine
container_name: traefik
networks:
- traefik_net
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
- ./acme.json:/acme.json
restart: unless-stopped
environment:
- OVH_ENDPOINT=ovh-eu
- OVH_APPLICATION_KEY=secretsecret
- OVH_APPLICATION_SECRET=secretsecret
- OVH_CONSUMER_KEY=secretsecret
labels:
- 'traefik.frontend.rule=Host:traefik.domain.name'
- 'traefik.port=8080'
- 'traefik.backend=traefik'
whoami:
image: containous/whoami
container_name: whoami
networks:
- traefik_net
labels:
- 'traefik.frontend.rule=Host:whoami.domain.name'
curl-client:
image: ubuntu
networks:
- traefik_net
command: sleep infinity
networks:
traefik_net:
external: true
Edit: The domain name is resolved using the following dnsmasq.conf:
domain-needed
expand-hosts
bogus-priv
interface=eno1
domain=domain.name
cache-size=1024
listen-address=127.0.0.1
bind-interfaces
dhcp-range=10.0.10.10,10.0.10.100,24h
dhcp-option=3,10.0.10.1
dhcp-authoritative
server=208.67.222.222
server=208.67.220.220
address=/domain.name/10.0.10.3
After some investigation it seems that Traefik is not the problem here, the inability to access the container IP is due to the way Docker manages its internal network (see the following comments: https://github.com/containous/traefik/issues/4352 and https://github.com/docker/for-mac/issues/180).
I was able to achieve my goal of whitelisting internal connections by running my openvpn container in nework_host mode, this way the client is assigned an IP by the system directly.