The corporate DNS server that is outside of our control doesn't handle AAAA queries properly. When sent a AAAA query, the DNS server doesn't respond. A properly working DNS server returns NOERROR, ANSWER: 0, if there is no AAAA record for a given name. Misconfigured DNS server doesn't send any response.
In an IPv6-enabled environment, the client tries to resolve both A and AAAA addresses. If the DNS server doesn't send any reply, the client repeats the query and eventually times out. Only after the AAAA query times out, the client will use the A address. Waiting for the timeouts renders utilities like curl, kubectl, oc, ... and others unusable.
This command hangs (>10 secs) before it prints out the web page:
$ curl https://google.com
This command fetches the page instantly:
$ curl -4 https://google.com
$ NAMESERVER=<your name server here>
This query returns an answers:
$ dig @$NAMESERVER A google.com
This query times out and doesn't return an answer:
dig @$NAMESERVER AAAA google.com
The idea is to use a custom DNS server which:
- Forwards the A queries to the broken DNS server
- Replies to the AAAA queries by itself keeping the clients happy
Dnsmasq can be configured to achieve the above. It can be run on a local machine as a DNS cache server listening on localhost:53.
First, download the list of top-level domains. It will be needed to construct the dnsmasq configuration file:
$ curl -O https://data.iana.org/TLD/tlds-alpha-by-domain.txt
Next, clean up the TLD file:
$ sed -e '/^#/d' -e '/^XN--/d' tlds-alpha-by-domain.txt > tlds-alpha-by-domain.txt.clean
Construct the top part of the dnsmasq configuration file:
$ cat > dnsmasq.conf <<EOF
no-resolv
log-queries
no-hosts
EOF
Generate the rest of the config file:
$ NAMESERVER=<your name server here>
$ while read TLD; do \
echo address=/$TLD/::; \
echo server=/$TLD/$NAMESERVER; \
done < tlds-alpha-by-domain.txt.clean >> dnsmasq.conf
Your dnsmasq.conf file should now look as follows (output was shortened):
$ cat dnsmasq.conf
no-resolv
log-queries
no-hosts
address=/AAA/::
server=/AAA/<your name server here>
address=/AARP/::
server=/AARP/<your name server here>
address=/ABARTH/::
server=/ABARTH/<your name server here>
...
Using the above config file, you can start the DNS cache server:
$ sudo dnsmasq --no-daemon -C dnsmasq.conf
Next, edit the /etc/resolv.conf
file to configure your machine to use the DNS cache server instead of the broken DNS server:
$ cat /etc/resolv.conf
...
nameserver 127.0.0.1
...
You are all set. The DNS resolution on your machine should work now!
That's helpful, thanks