I have a test environment using Docker, in which I am utilizing Traefik as a reverse proxy to manage network traffic within my intranet. I am using step-ca as my ACME server. Since this a test setup I'm just importing root-crt generated by step-ca to all my devices and trusting it, which will give that sweet green lock icon. I'm facing issues with DNS challenge and wildcard cert generation, which I have detailed below
My Traefik docker-compose.yaml
---
services:
traefik:
image: docker.io/library/traefik:latest
container_name: traefik
restart: unless-stopped
networks:
proxy:
ipv4_address: 172.18.0.10
ports:
- 80:80
- 443:443
environment:
# root cert the traefik should trust for acme to work
- LEGO_CA_CERTIFICATES=/usr/local/share/ca-certificates/root_ca.crt
# Env variables as per documentation
- RFC2136_TSIG_KEY=keyname.
- RFC2136_TSIG_SECRET= < Key generated defined by certbot documentation>
- RFC2136_TSIG_ALGORITHM=hmac-sha512.
- RFC2136_NAMESERVER=192.168.1.50
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/config/traefik.yml:/traefik.yml:ro
- ./data/config/config.yml:/config.yml:ro
- ./data/config/acme.json:/acme.json
- ./data/logs:/var/log/traefik
# root certs from step-ca docker container bind
- ./data/step/certs:/usr/local/share/ca-certificates
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`dash.silverdev.fun`)"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`dash.silverdev.fun`)"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=dnsresolver"
- "traefik.http.routers.traefik-secure.tls.domains[0].main=silverdev.fun"
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.silverdev.fun"
- "traefik.http.routers.traefik-secure.service=api@internal"
networks:
proxy:
external: true
name: proxy
And my traefik.yaml
api:
dashboard: true
debug: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yml
certificatesResolvers:
myresolver:
acme:
email: admin@silver1618.fun
storage: acme.json
# step-ca and traefik are in the same network
caServer: https://step-ca:9000/acme/acme/directory
httpChallenge:
entryPoint: http
dnsresolver:
acme:
email: admin@silver1618.fun
storage: acme.json
caServer: https://step-ca:9000/acme/acme/directory
dnsChallenge:
provider: rfc2136
disablePropagationCheck: true
resolvers:
- "192.168.1.50:53" # BIND9 selfhosted DNS server, will resolve *.silverdev.fun
log:
level: "DEBUG"
filePath: "/var/log/traefik/traefik.log"
accessLog:
filePath: "/var/log/traefik/access.log"
While I am able to obtain certificates for all individual *.silverdev.fun internal domains using the HTTP-01 challenge, my goal was to secure a wildcard certificate using the DNS challenge. The most relevant solution I found in the documentation was the RCF2136 provider. Consequently, I set up a BIND9 server and correctly configured all the records as follows:
named.conf
cl home {
192.168.1.0/24;
172.18.0.0/24;
};
options {
version "not currently available";
forwarders {
1.1.1.1;
1.0.0.1;
};
allow-query { home; };
};
key "keyname." {
algorithm hmac-sha512;
secret "key as generated by tsig-keygen -a hmac-sha512 keyname.";
};
zone "silverdev.fun." IN {
type master;
file "/etc/bind/silver-dev.zone";
update-policy {
grant keyname. zonesub any;
};
};
and /etc/bind/silver-dev.zone
$ORIGIN .
$TTL 120 ; 2 minutes
silverdev.fun IN SOA ns.silverdev.fun. admin.silverdev.fun. (
2024040419 ; serial
43200 ; refresh (12 hours)
900 ; retry (15 minutes)
1814400 ; expire (3 weeks)
7200 ; minimum (2 hours)
)
NS ns.silverdev.fun.
A 192.168.1.19
$ORIGIN silverdev.fun.
* CNAME silverdev.fun.
ns A 192.168.1.19
With this configuration, I can successfully obtain a wildcard certificate when I employ certbot in the following manner:
docker run -it --rm --name certbot -e REQUESTS_CA_BUNDLE=/home/root.crt -p 80:80 --network="proxy" \
-v "./data/etc:/etc/letsencrypt" \
-v "./data/var:/var/lib/letsencrypt" \
-v "./data/secrets:/home" \
-v "./data/certs/root_ca.crt:/home/root.crt" \
certbot/dns-rfc2136 certonly --dns-rfc2136 --dns-rfc2136-credentials /home/dns.ini \
--agree-tos --email admin@silverdev.fun \
--server https://step-ca:9000/acme/acme/directory -d "silverdev.fun" -d "*.silverdev.fun"
However, when I execute the Traefik container, I observe in the bind9 logs that Traefik is generating _acme challenge CNAME records. It doesn't succeed in obtaining the wildcard certificate, but it does manage to secure the certificate for the base domain silverdev.fun. I need help regarding this
Bind9 logs
bind9 | 05-Apr-2024 12:33:09.127 client @0x7f6f8c1a51a8 192.168.1.19#33150/key keyname: updating zone 'silverdev.fun/IN': deleting rrset at 'silverdev.fun' TXT
bind9 | 05-Apr-2024 12:33:09.127 client @0x7f6f8c1a51a8 192.168.1.19#33150/key keyname: updating zone 'silverdev.fun/IN': adding an RR at 'silverdev.fun' TXT "RQ3qmr5eNGhArjvNHNZLD8YQWMpNv08JMP25q3KaBzc"
bind9 | 05-Apr-2024 12:41:02.534 client @0x7f6f8c1a51a8 192.168.1.19#57644/key keyname: updating zone 'silverdev.fun/IN': deleting an RR at silverdev.fun TXT
bind9 | 05-Apr-2024 12:41:02.574 client @0x7f6f8c1a51a8 192.168.1.19#58325/key keyname: updating zone 'silverdev.fun/IN': deleting rrset at 'silverdev.fun' TXT
bind9 | 05-Apr-2024 12:41:02.574 client @0x7f6f8c1a51a8 192.168.1.19#58325/key keyname: updating zone 'silverdev.fun/IN': adding an RR at 'silverdev.fun' TXT "VISe2Q1m1v0FGkRWsORIOw-N41jI884NNXPgtL6Bg7Q"
traefik logs
time="2024-04-05T12:33:06+05:30" level=debug msg="https://step-ca:9000/acme/acme/directory" providerName=dnsresolver.acme
time="2024-04-05T12:33:06+05:30" level=debug msg="Using DNS Challenge provider: rfc2136" providerName=dnsresolver.acme
time="2024-04-05T12:33:06+05:30" level=debug msg="legolog: [INFO] [silverdev.fun, *.silverdev.fun] acme: Obtaining bundled SAN certificate"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [silverdev.fun] AuthURL: https://step-ca:9000/acme/acme/authz/hYVAdEI2UYwpTA0ISbdfy99tsj079aDI"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [*.silverdev.fun] AuthURL: https://step-ca:9000/acme/acme/authz/zoraVKcehBHDVP1yX210YMoRdmtzA4Sg"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [silverdev.fun] acme: Could not find solver for: http-01"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [silverdev.fun] acme: use dns-01 solver"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [*.silverdev.fun] acme: use dns-01 solver"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [silverdev.fun] acme: Preparing to solve DNS-01"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] Found CNAME entry for \"_acme-challenge.silverdev.fun.\": \"silverdev.fun.\""
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [silverdev.fun] acme: Trying to solve DNS-01"
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] Found CNAME entry for \"_acme-challenge.silverdev.fun.\": \"silverdev.fun.\""
time="2024-04-05T12:33:09+05:30" level=debug msg="legolog: [INFO] [silverdev.fun] acme: Checking DNS record propagation using [192.168.1.50:53]"
time="2024-04-05T12:33:11+05:30" level=debug msg="legolog: [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]"
time="2024-04-05T12:41:02+05:30" level=debug msg="legolog: [INFO] [silverdev.fun] acme: Cleaning DNS-01 challenge"
time="2024-04-05T12:41:02+05:30" level=debug msg="legolog: [INFO] Found CNAME entry for \"_acme-challenge.silverdev.fun.\": \"silverdev.fun.\""
time="2024-04-05T12:41:02+05:30" level=debug msg="legolog: [INFO] [*.silverdev.fun] acme: Preparing to solve DNS-01"
time="2024-04-05T12:41:02+05:30" level=debug msg="legolog: [INFO] Found CNAME entry for \"_acme-challenge.silverdev.fun.\": \"silverdev.fun.\""
time="2024-04-05T12:41:02+05:30" level=debug msg="legolog: [INFO] [*.silverdev.fun] acme: Trying to solve DNS-01"
time="2024-04-05T12:41:02+05:30" level=debug msg="legolog: [INFO] Found CNAME entry for \"_acme-challenge.silverdev.fun.\": \"silverdev.fun.\""
time="2024-04-05T12:41:02+05:30" level=debug msg="legolog: [INFO] [*.silverdev.fun] acme: Checking DNS record propagation using [192.168.1.50:53]"
time="2024-04-05T12:41:04+05:30" level=debug msg="legolog: [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]"