Fixing SERVFAIL DNS Resolution for AWS Console with Pi-hole + Unbound
If you're running Pi-hole with Unbound in Docker containers and hit a SERVFAIL
when trying to access the AWS Console, this post is for you.
I run Pi-hole and Unbound in side-by-side containers using Docker Compose. Recently, DNS lookups to console.aws.amazon.com
began failing intermittently with a SERVFAIL
.
π₯ The Problemβ
Access to console.aws.amazon.com
failed, and Pi-hole logs showed:
query\[A] console.aws.amazon.com from 172.16.2.35
cached console.aws.amazon.com is <CNAME>
...
forwarded console.aws.amazon.com to 192.168.0.2
reply error is SERVFAIL
Unbound logs were repetitive and useless at first glance:
info: generate keytag query \_ta-4f66-9728. NULL IN
This pointed to: DNSSEC validation failure, specifically with Unboundβs trust anchor setup.
π Root Causeβ
Unbound uses DN SSEC by default to validate domain authenticity. AWS domains like console.aws.amazon.com
involve:
- Deep CNAME chains
- Regional DNS records
- DNSSEC-enabled responses
When Unboundβs DNSSEC trust anchor is outdated or misconfigured, it can't verify these chains and returns SERVFAIL
.
That log line?
generate keytag query _ta-4f66-9728. NULL IN
It means Unbound is repeatedly querying for the DNS trust anchor _ta-4f66-9728
, likely because:
- The trust anchor expired.
- The
root.key
file was never updated. - Or your container doesnβt run
unbound-anchor
regularly.
π§ͺ Step-by-Step Diagnosisβ
Hereβs how I verified the issue:
From the host, run:
dig console.aws.amazon.com @192.168.0.2
β
SERVFAIL
From inside Unbound container:
docker exec -it unbound dig console.aws.amazon.com @127.0.0.1
β also
SERVFAIL
Check logs:
docker logs unbound | grep ta-4f66
β endless keytag queries = broken DNSSEC validation
Temporarily switch Pi-hole to 1.1.1.1 or 8.8.8.8 as upstream β everything worked again.
β The Fix (Recommended)β
Since DNSSEC isn't critical in my setup and updating trust anchors in Docker regularly is annoying, I disabled DNSSEC in Unbound:
π Edit unbound.conf
(or pi-hole.conf
)β
Make sure this is in your config:
server:
# ... other config ...
dnssec-validation: no
Then restart the container:
docker restart unbound
π Thatβs it. All AWS domains resolve cleanly now, no SERVFAIL
.
π§° Optional: Update DNSSEC Trust Anchors (if you want to keep DNSSEC)β
If you do want to keep DNSSEC on, youβll need to:
Download a fresh root trust anchor:
curl -o root.key https://data.iana.org/root-anchors/root-anchors.xml
Mount
root.key
into the container:volumes:
- ./root.key:/etc/unbound/root.keyAdd to Unbound config:
trust-anchor-file: "/etc/unbound/root.key"
Restart Unbound.
Youβll need to update this file regularly unless you automate it with unbound-anchor
, which is non-trivial in a minimal container setup.
π³ Docker Networking Tipsβ
Make sure both containers are on a user-defined Docker network:
docker network create dns-net
Then update your Compose:
services:
unbound:
container_name: unbound
image: mvance/unbound:latest
networks:
- dns-net
...
pihole:
container_name: pihole
image: pihole/pihole:latest
networks:
- dns-net
environment:
- PIHOLE_DNS_=unbound#53
...
networks:
dns-net:
Using container names (unbound#53
) avoids needing IPs.
π§© Summaryβ
Symptom | Cause | Fix |
---|---|---|
SERVFAIL on AWS domains | DNSSEC trust anchor outdated | Disable DNSSEC or update trust anchor |
Endless _ta-4f66-9728 queries | Root key not valid or missing | Use dnssec-validation: no in Unbound |
Works with 1.1.1.1 but not Unbound | Confirms internal resolver issue | Fix Unbound, not Pi-hole |
π§ Final Thoughtsβ
If you're running Pi-hole + Unbound in containers, youβre likely doing it for privacy, not full DNSSEC correctness. Disabling DNSSEC is a valid tradeoff unless you're actively auditing DNS trust chains.
Pi-hole is powerful, but issues like these can sneak in when upstream resolvers fail quietly and you only see the downstream effect like well-known domains failing to resolve.
Anyway, a possible fix if you find yourself in the same situation.
This document is an AI summary of a troubleshooting session I had with my AI, formatted for blog consumption.