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"
- "--certificatesresolvers.le.acme.email=wkill95@gmail.com"
- "--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
I had the same issue. The problem is that Traefik blocks the dot
ALPN extension per default.
docker compose logs
after kdig request showed:
tls: client requested unsupported application protocols ([dot])
You can test this with openssl, too:
$ openssl s_client -alpn dot -connect mydnshere:853
...
No ALPN negotiated
You can configure ALPN extensions for traefik with Docker as follows.
Additions to compose.yaml (rename service / router names accordingly):
services:
traefik:
image: "traefik:v2.9"
command:
# Provider Config
- "--providers.file.filename=/etc/traefik/config.toml"
volumes:
- ./config.toml:/etc/traefik/config.toml
blocky:
image: spx01/blocky
labels:
- "traefik.tcp.routers.blocky-dns.rule=HostSNI(`my.fqn.com`)"
- "traefik.tcp.routers.blocky-dns.tls.options=dot@file"
Add config.toml
[tls.options]
[tls.options.dot]
alpnProtocols = ["dot"]
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).