Traefik and PiHole with Docker: forward client IP

I currently got in touch with Traefik and using it as reverse proxy for my docker services. So far everything works fine, except the fact that the client IP addresses aren't forwarded but only the internal docker IP from Traefik is shown. How can i make the original client IP addresses available to my services?

As a minimal setup example I use Traefik and PiHole. With following configurations:

docker-compose.traefik.yml

version: "3"

services:

  traefik:
    container_name: traefik
    image: traefik
    restart: always
    networks:
      - local
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 80:80/tcp
      - 443:443/tcp
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "traefik:/etc/traefik/"
    command:
      - "--global.checknewversion=true"
      - "--global.sendanonymoususage=false"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.file.directory=/etc/traefik/config"
      - "--providers.file.watch=true"
      - "--entrypoints.dnstcp.address=:53/tcp"
      - "--entrypoints.dnsudp.address=:53/udp"
      - "--entrypoints.http.address=:80/tcp"
      - "--entrypoints.http.http.redirections.entryPoint.to=https"
      - "--entrypoints.http.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.https.address=:443/tcp"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=https"
      - "traefik.http.routers.traefik.tls=true"
      - "traefik.http.routers.traefik.rule=Host(`traefik.raspberrypi.local`)"
      - "traefik.http.routers.traefik.service=api@internal"
      
volumes:
  traefik:
    name: traefik
    
networks:
  local:
    name: local

dynamic_config.yml

tls:
  certificates:
    - certFile: /etc/traefik/certs/raspberrypi.local.crt
      keyFile: /etc/traefik/certs/raspberrypi.local.key

docker-compose.pihole.yml

version: "3"

services:

  pihole:
    container_name: pihole
    image: pihole/pihole
    restart: always
    networks:
      - local
    environment:
      TZ: "Europe/Berlin"
    volumes:
      - "/var/lib/docker/volumes/pihole/_data/etc-pihole/:/etc/pihole/"
      - "/var/lib/docker/volumes/pihole/_data/etc-dnsmasq.d/:/etc/dnsmasq.d/"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.pihole.entrypoints=https"
      - "traefik.http.routers.pihole.tls=true"
      - "traefik.http.routers.pihole.rule=Host(`pihole.raspberrypi.local`)"
      - "traefik.http.routers.pihole.middlewares=pihole-prefix"
      - "traefik.http.middlewares.pihole-prefix.addPrefix.prefix=/admin"
      - "traefik.http.services.pihole.loadbalancer.server.port=80"

      - "traefik.tcp.routers.dnstcp.entrypoints=dnstcp"
      - "traefik.tcp.routers.dnstcp.rule=HostSNI(`*`)"
      - "traefik.tcp.services.pihole.loadbalancer.server.port=53"

      - "traefik.udp.routers.dnsudp.entrypoints=dnsudp"
      - "traefik.udp.services.pihole.loadbalancer.server.port=53"

volumes:
  pihole:
    name: pihole
    
networks:
  local:
    name: local

When using Traefik only one IP (domain) shows in the client list. Which actual is the internal docker IP of Traefik. Without using Traefik the list shows all the local network IP addresses.

I am wondering if this has to do with the POST HOST HEADER of the UDP service, which seems to be by default set to false?

I did not manage turning it to true. Adding this to the UDP service did not help and made Traefik crash:
- "traefik.udp.services.pihole.loadbalancer.passHostHeader=true"

But maybe the problem is somewhere else?

Thanks for any help in advance!

Have you managed to solve the issue? I am having the exact same thing.

I have been using pihole as a docker setup for years. I just set up a second pihole instance behind Traefik and I found the exact same issue.

Switch traefik to use network_mode host.

But then how to connect other container/services (like pihole) in bridge mode (?) to traefik?
Could you give a small example with treafik running network_mode host and any other services is connected to (routed through) it?

Many thanks in advance! :slight_smile:

I doesn't change the docker networking only how the ports are exposed.

@chris Did you ever solve this?

@chris @mitchross Were you guys able to resolve this? I am using this in kubernetes to receive UDP traffic for snmptraps, but facing this same issue.

When using http, the original IP is included in the headers.

When using TCP, you can use ProxyProtocol (doc), but the target must be able to handle it.

AFAIK there is no solution for UDP to relay the original IP.