I have a problem configuring my traefik + pihole setup. I want to configure dns over tls. Maybe someone can point me out in right directions?
In debug process, i found about tool kdig
. I have tried it:
kdig -d @myiphere +tls-ca +tls-host=mydnshere example.com 07:36:12
;; DEBUG: Querying for owner(example.com.), class(1), type(1), server(myiphere), port(853), protocol(TCP)
;; DEBUG: TLS, imported 127 system certificates
;; WARNING: TLS, handshake failed (A TLS fatal alert has been received.)
Okay, so maybe a certificate is wrong? It does not look like it:
openssl s_client -connect mydnshere:853
CONNECTED(00000003)
/***bunch of text here***/
SSL handshake has read 5070 bytes and written 382 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 4096 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
---
Post-Handshake New Session Ticket arrived:
/***bunch of text here***/
Can someone point me out in right direction or tell what i am missing?
I have to mention that dig domain.com @myiphere
and dig +tcp domain.com @myiphere
are working fine.
Here is my configs:
traefik:
version: "3.8"
services:
reverse-proxy:
image: traefik
restart: unless-stopped
command:
- "--api=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.dns.address=:53"
- "--entrypoints.dot.address=:853"
- "--entrypoints.dns-udp.address=:53/udp"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.vpn-udp.address=:51820/udp"
- "--entrypoints.syncthing-tcp.address=:20000"
- "--entrypoints.syncthing-udp.address=:20000/udp"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "[email protected]"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.le.acme.httpchallenge=true"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
- "--pilot.token=${TRAEFIK_PILOT_TOKEN:-}"
- "--serversTransport.insecureSkipVerify=true"
- "--log.level=${TRAEFIK_LOG_LEVEL:-ERROR}"
ports:
# TODO: found out how to show remote ip in pihole
#- "53:53"
#- "53:53/udp"
- "853:853"
# The HTTP port
- "80:80"
- "443:443"
# VPN
- "51820:51820/udp"
# The Web UI (enabled by --api.insecure=true)
#- "8080:8080"
# Syncthing
- "22000:22000"
- "22000:22000/udp"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik_certs:/letsencrypt
networks:
- reverse-proxy
dns:
- 1.1.1.1
- 1.0.0.1
labels:
- "traefik.enable=true"
- "traefik.http.routers.api-data.rule=Host(`${TRAEFIK_API_DOMAIN?No traefik api domain set}`) && ( Path(`/api/version`) || PathPrefix(`/api/http/`) || PathPrefix(`/api/tcp/`))"
- "traefik.http.routers.api-data.entrypoints=websecure"
- "traefik.http.routers.api-data.service=api@internal"
- "traefik.http.routers.api-data.tls=true"
- "traefik.http.routers.api-data.tls.certresolver=${TRAEFIK_API_CERTRESOLVER?No traefik api certificate resolver}"
- "traefik.http.routers.api.rule=Host(`${TRAEFIK_API_DOMAIN?No traefik api domain set}`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.tls=true"
- "traefik.http.routers.api.tls.certresolver=${TRAEFIK_API_CERTRESOLVER?No traefik api certificate resolver}"
- "traefik.http.routers.api.middlewares=authelia@docker"
- "flame.type=application"
- "flame.name=Traefik"
- "flame.url=https://${TRAEFIK_API_DOMAIN}"
- "flame.icon=router-network"
volumes:
traefik_certs:
networks:
reverse-proxy:
name: reverse-proxy
pihole:
version: '3.8'
services:
pihole:
image: pihole/pihole
restart: unless-stopped
env_file: pihole.environment
cap_add:
- CAP_NET_ADMIN
networks:
- reverse-proxy
dns:
- 127.0.0.1
- 1.1.1.1
ports:
- 53:53/tcp
- 53:53/udp
volumes:
- 'pihole_configs:/etc/pihole/'
labels:
- "traefik.enable=true"
- "traefik.docker.network=reverse-proxy"
- "traefik.http.routers.pihole-api.rule=Host(`${PIHOLE_DOMAIN:?No pihole domain set}`) && Path(`/admin/api.php`)"
- "traefik.http.routers.pihole-api.tls=true"
- "traefik.http.routers.pihole-api.tls.certresolver=${PIHOLE_CERTRESOLVER?No pihole certificate resolver}"
- "traefik.http.routers.pihole-api.entrypoints=websecure"
- "traefik.http.routers.pihole-api.service=pihole"
- "traefik.http.services.pihole-api.loadBalancer.server.port=80"
- "traefik.http.routers.pihole.rule=Host(`${PIHOLE_DOMAIN:?No pihole domain set}`)"
- "traefik.http.routers.pihole.tls=true"
- "traefik.http.routers.pihole.tls.certresolver=${PIHOLE_CERTRESOLVER?No pihole certificate resolver}"
- "traefik.http.routers.pihole.entrypoints=websecure"
- "traefik.http.routers.pihole.service=pihole"
- "traefik.http.routers.pihole.middlewares=authelia@docker"
- "traefik.http.services.pihole.loadBalancer.server.port=80"
- "flame.type=application"
- "flame.name=DNS"
- "flame.url=https://${PIHOLE_DOMAIN}/admin"
- "flame.icon=pi-hole"
- "traefik.tcp.routers.dnsovertls.rule=HostSNI(`mydnshere`)"
- "traefik.tcp.routers.dnsovertls.entrypoints=dot"
- "traefik.tcp.routers.dnsovertls.tls.certresolver=le"
- "traefik.tcp.routers.dnsovertls.service=pihole"
# Normal DNS coming in on 53 TCP, no TLS
- "traefik.tcp.routers.dns.rule=HostSNI(`*`)"
- "traefik.tcp.routers.dns.entrypoints=dns"
- "traefik.tcp.routers.dns.service=pihole"
# recieves traffic from both the TLS and non-TLS traefik routers
- "traefik.tcp.services.pihole.loadbalancer.server.port=53"
# Normal DNS coming in on 53 UDP
- "traefik.udp.routers.udpdns.entrypoints=dns-udp"
- "traefik.udp.routers.udpdns.service=pihole"
- "traefik.udp.services.pihole.loadbalancer.server.port=53"
volumes:
pihole_configs:
networks:
reverse-proxy:
external: true
2
Answers
I am trying to understand what you are attempting to do here. Do you want to use Traefik as a proxy for Pihole DNS resolution attempts? I don’t think that works out well, because you are using Traefik as a reverse proxy for your services.
Traefik handles incoming connections from the outside and sends back the corresponding answers. In case Pihole on its own decides to do a lookup it never goes through Traefik, as far as I know. You got to configure a separate service for secured lookups, like stubby or cloudflared. I recommend cloudflared (it does encrypted lookups via DoH), as there is an official guide in their documentation.
Apart from that, the DNS field inside the docker compose file is for the docker container environment. But that’s not where you configure the DNS address for Pihole lookups, you have to do that inside the Pihole application settings.
I had the same issue. The problem is that Traefik blocks the
dot
ALPN extension per default.docker compose logs
after kdig request showed:You can test this with openssl, too:
You can configure ALPN extensions for traefik with Docker as follows.
Additions to compose.yaml (rename service / router names accordingly):
Add config.toml
Here is some background about ALPN dot: https://gitlab.isc.org/isc-projects/bind9/-/issues/2794
Update Removed the ALPN filter in the tcp router configuration as some clients do not advertise dot in ALPN (for example Android).