Introduction

AAAA records map hostnames to IPv6 addresses, and when they go wrong, the symptoms are confusing. A dual-stack client receives an IPv6 address and attempts to connect, but the connection hangs or fails. Meanwhile, the same service works perfectly over IPv4. The problem often appears as mysterious timeouts, broken half of connections, or inconsistent behavior across clients.

Symptoms

IPv6 connections fail while IPv4 works, often with confusing timeout errors:

``` # AAAA record query returns nothing dig example.com AAAA +short # (empty response)

# But A record works dig example.com A +short 192.168.1.100

# Connection hangs on IPv6-capable clients curl -6 http://example.com curl: (28) Connection timed out after 30000 milliseconds

# getaddrinfo returns AAAA but connection fails getent ahosts example.com 2001:db8::1 STREAM example.com 192.168.1.100 STREAM example.com ```

Browser shows "Connection timed out" or "Unable to connect" only on IPv6 networks:

bash
ERR_CONNECTION_TIMED_OUT
# IPv4 fallback works, but pure IPv6 networks cannot reach the site

Common Causes

  1. 1.AAAA record never created - IPv6 deployment incomplete, A record exists but AAAA skipped
  2. 2.AAAA points to wrong IPv6 address - Stale address, typo in address, wrong subnet
  3. 3.AAAA exists but IPv6 not routed - Record published but no route to the prefix
  4. 4.IPv6 service not listening - AAAA correct but service not bound to IPv6
  5. 5.Firewall blocking IPv6 - IPv4 allowed, IPv6 dropped silently
  6. 6.Dnssec validation failure - AAAA record signed with wrong key or broken chain

Step-by-Step Fix

Step 1: Diagnose AAAA Record Issues

Query for AAAA records specifically:

```bash # Basic AAAA query dig example.com AAAA

# Short answer only dig example.com AAAA +short

# Query authoritative nameserver dig @ns1.example.com example.com AAAA

# Check both A and AAAA together dig example.com ANY +short ```

Using nslookup:

bash
nslookup -type=AAAA example.com
nslookup -type=AAAA example.com 8.8.8.8

Check if AAAA record exists in the zone:

```bash # For BIND zones grep -i "aaaa" /etc/bind/db.example.com

# For PowerDNS pdnsutil list-zone example.com | grep AAAA

# For Active Directory Get-DnsServerResourceRecord -ZoneName example.com -RRType AAAA ```

Step 2: Verify IPv6 Address Is Correct and Routable

Test if the IPv6 address is reachable:

```bash # Ping the IPv6 address directly ping6 2001:db8::1 ping -6 2001:db8::1

# Check routing ip -6 route get 2001:db8::1 traceroute6 2001:db8::1

# Test TCP connectivity to port 80/443 nc -6 -zv 2001:db8::1 80 nc -6 -zv 2001:db8::1 443

# Using telnet telnet -6 2001:db8::1 80 ```

Verify the server has the IPv6 address assigned:

```bash # On the target server ip -6 addr show ip addr show | grep inet6

# Check if service listens on IPv6 ss -tlnp | grep ":80|:443" netstat -tlnp | grep ":::" ```

Step 3: Create or Fix AAAA Records

Add AAAA record to BIND zone file:

```bash # Edit zone file sudo vi /etc/bind/db.example.com

# Add AAAA record example.com. IN AAAA 2001:db8:85a3::8a2e:370:7334 www.example.com. IN AAAA 2001:db8:85a3::8a2e:370:7334

# Increment SOA serial (required!) # Change: 2024031501 to 2024031502

# Check zone syntax named-checkzone example.com /etc/bind/db.example.com

# Reload zone sudo rndc reload example.com sudo systemctl reload named ```

Using nsupdate:

bash
nsupdate << EOF
server ns1.example.com
zone example.com
update add example.com. 3600 IN AAAA 2001:db8:85a3::8a2e:370:7334
send
EOF

For Active Directory DNS:

powershell
Add-DnsServerResourceRecord -AAAA -Name "www" -ZoneName "example.com" `
    -IPv6Address "2001:db8:85a3::8a2e:370:7334" -TimeToLive 3600

For Cloudflare API:

bash
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "AAAA",
    "name": "example.com",
    "content": "2001:db8:85a3::8a2e:370:7334",
    "ttl": 3600,
    "proxied": false
  }'

Step 4: Fix IPv6 Service Binding

Ensure the service listens on IPv6:

nginx
# Nginx - listen on IPv6
server {
    listen 80;
    listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com;
}
apache
# Apache - listen on IPv6
Listen 80
Listen [::]:80
Listen 443
Listen [::]:443
bash
# Verify service binding
ss -tlnp | grep -E ":(80|443)"
# Should show both 0.0.0.0:80 and :::80

Step 5: Check Firewall Rules

```bash # Check ip6tables rules sudo ip6tables -L -n -v

# Allow IPv6 HTTP/HTTPS sudo ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT sudo ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT

# Save rules sudo ip6tables-save > /etc/iptables/rules.v6

# For firewalld sudo firewall-cmd --add-service=http --permanent sudo firewall-cmd --add-service=https --permanent sudo firewall-cmd --reload

# Verify sudo firewall-cmd --list-all ```

Step 6: Handle DNSSEC for AAAA Records

If the zone is DNSSEC-signed, re-sign after adding AAAA:

```bash # Re-sign zone after AAAA addition dnssec-signzone -A -3 $(head -c 1000 /dev/urandom | sha1sum | cut -b 1-16) \ -N INCREMENT -o example.com -t db.example.com

# Or with dynamic DNSSEC rndc sign example.com

# Verify DNSSEC chain for AAAA dig @8.8.8.8 example.com AAAA +dnssec +multi ```

Step 7: Verify End-to-End IPv6 Connectivity

```bash # Query from public resolvers dig @8.8.8.8 example.com AAAA +short dig @1.1.1.1 example.com AAAA +short

# Force IPv6 connection curl -6 -v https://example.com

# Test from external IPv6 testing site curl -6 https://ipv6.example.com ```

Common Pitfalls

  • Forgetting to increment SOA serial - Zone transfers will not propagate the new AAAA record
  • Using link-local addresses - AAAA with fe80:: addresses are not routable
  • Mixing up IPv6 notation - Double colon :: can only appear once per address
  • AAAA points to server without IPv6 - Record exists but server has no IPv6 configured
  • Proxy/proxy enabled for AAAA - Cloudflare proxy does not support AAAA-only (no A record) setups
  • TTL too high - Long TTL delays recovery from wrong AAAA records

Best Practices

  • Create AAAA records at the same time as A records for all new hostnames
  • Use shorter TTL (300-600s) during IPv6 deployment phases
  • Test IPv6 connectivity before publishing AAAA records
  • Monitor IPv6 reachability alongside IPv4
  • Consider AAAA record health checks that verify actual IPv6 service availability
  • Document IPv6 addressing scheme to avoid typos
  • DNS A Record Not Propagating
  • IPv6 Connectivity Issues
  • DNS Round Robin Not Working
  • DNSSEC Validation Failure
  • DNS Zone Transfer Problems