Skip to content

Instantly share code, notes, and snippets.

@noseka1
Last active August 7, 2024 09:25
Show Gist options
  • Save noseka1/6b7cbeca199db9c4823324bc31214bb2 to your computer and use it in GitHub Desktop.
Save noseka1/6b7cbeca199db9c4823324bc31214bb2 to your computer and use it in GitHub Desktop.

How to disable AAAA lookups?

Problem description

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.

Identifying the AAAA lookup problem

Check using curl

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

Check by querying the DNS server

$ 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

Working around the issue

The idea is to use a custom DNS server which:

  1. Forwards the A queries to the broken DNS server
  2. 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.

Configuring Dnsmasq

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!

References

How to disable AAAA lookups?

@sabretus
Copy link

sabretus commented Aug 6, 2021

That's helpful, thanks

@easymoney322
Copy link

easymoney322 commented Aug 7, 2024

I wasn't able to fully block answers, as they would still return "::" and this was undesired behaviour for me.

However, I was able to achieve blocking of IPv6 answers by using DNSMASQ_OPTS="--filter-AAAA" instead in /etc/default/dnsmasq.

~# nslookup ifconfig.me 127.0.0.1
Server:         127.0.0.1
Address:        127.0.0.1#53

Non-authoritative answer:
Name:   ifconfig.me
Address: 34.160.111.145

Please note that if you planning to use this option, you will need to remove these server and address lines from the config file.

You can also modify systemd service unit file if you don't have the defaults file, or just call the binary file directly with required arguments.

Disabling IPv6 with such sysctl doesn't affect resolving v6 addresses sadly.
If filtering AAAA requests with arguments isn't enough, your next best bet is to just recompile from source and disable IPv6 as an option.

I've installed my dnsmasq through debian's packet manager, and these are default options that are being printed after the dnsmasq launch:
dnsmasq[7822]: compile time options: IPv6 GNU-getopt DBus no-UBus i18n IDN2 DHCP DHCPv6 no-Lua TFTP conntrack ipset nftset auth cryptohash DNSSEC loop-detect inotify dumpfile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment