Windows AAAA Record Query Behavior: Why IPv6 DNS Lookups Occur Without Routable IPv6 Addresses


7 views

When troubleshooting Windows DNS resolution issues in IPv4-only networks, I've observed that Windows clients occasionally attempt IPv6 (AAAA record) queries even without being assigned a routable IPv6 address. This behavior persists across Windows 7 and Vista, causing intermittent resolution failures despite proper IPv4 configuration.

The symptoms manifest when:

  • Clients receive IPv4 addresses via DHCP
  • DNS suffix ("internal" in this case) is properly assigned
  • Standard commands like ping fail while nslookup succeeds
# Failing commands:
ping domain-name
ping -4 domain-name

# Working alternatives:
nslookup domain-name
ping domain-name.internal

Examining the DNS cache via ipconfig /displaydns shows telltale signs:

domain-name
----------------------------------------
No records of type AAAA

This indicates Windows is attempting IPv6 resolution despite lacking global IPv6 connectivity.

Windows implements RFC 3484 (Default Address Selection for IPv6) which mandates:

  1. Simultaneous A and AAAA record queries for dual-stack systems
  2. Negative caching of failed AAAA queries
  3. No fallback mechanism when AAAA queries fail

This becomes problematic when:

  • DNS servers don't properly handle AAAA queries
  • Network has no IPv6 connectivity
  • DNS servers drop subsequent A record queries after AAAA failures

Solution 1: Registry Modification (Permanent Fix)

Disable IPv6 DNS queries while keeping IPv6 stack operational:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters]
"DisableParallelAandAAAA"=dword:00000001

Solution 2: Network Adapter Reset (Temporary Fix)

netsh interface ipv6 delete neighbors
netsh interface set interface "Ethernet" disable
netsh interface set interface "Ethernet" enable

Solution 3: DNS Suffix Workaround

Force FQDN resolution by appending the internal domain:

ping domain-name.internal
nslookup domain-name.internal

For more granular control, use these PowerShell commands:

# Check DNS client configuration
Get-DnsClient | Select-Object InterfaceAlias, ConnectionSpecificSuffix

# Clear DNS cache
Clear-DnsClientCache

# Test resolution with specific record types
Resolve-DnsName domain-name -Type A
Resolve-DnsName domain-name -Type AAAA -ErrorAction SilentlyContinue

Using Wireshark or netsh, we can confirm the query pattern:

netsh trace start scenario=NetConnection capture=yes tracefile=dns.etl
ping domain-name
netsh trace stop

This typically shows sequential AAAA and A queries, with potential timeout delays between them.

  • Configure DNS servers to properly handle AAAA queries
  • Implement Group Policy for consistent DNS settings
  • Monitor DNS query success rates
  • Consider disabling IPv6 completely if unused
# Group Policy template for disabling IPv6 DNS queries
# Computer Configuration → Administrative Templates → Network → DNS Client
# "Turn off parallel A and AAAA queries" → Enabled

In networks where Windows clients (Vista/7) receive only IPv4 addressing via DHCP, we've observed an interesting DNS resolution pattern where machines intermittently fail to resolve local hostnames despite proper A records existing in the network's DNS server (ZyXEL ZyWall USG 100 in this case). The key indicators are:

C:\>ping domain-name
Ping request could not find host domain-name.

C:\>nslookup domain-name
Server:  router.internal
Address:  192.168.1.1

Name:    domain-name.internal
Address:  192.168.1.42

Windows DNS client behavior reveals the root cause through ipconfig /displaydns output showing failed AAAA record queries:

domain-name
----------------------------------------
No records of type AAAA

This occurs because Windows' DNS resolution process follows RFC 3484 (now obsoleted by RFC 6724) which mandates:

  1. Dual-stack queries (AAAA then A) by default
  2. No address family preference based on local connectivity

Windows DNS resolver implements a happy eyeballs-like algorithm where:

if (IPv6Enabled) {
    SendAAAAQuery();
    if (Timeout || SERVFAIL) {
        SendAQuery(); // Fallback
    }
} else {
    SendAQuery();
}

The critical implementation detail is that IPv6Enabled checks only for:

  • IPv6 protocol stack presence (always true post-Vista)
  • Not whether routable IPv6 addresses exist

We can simulate this with PowerShell:

# Force clean DNS cache
Clear-DnsClientCache

# Simulate broken DNS server (fails AAAA queries)
Add-DnsClientNrptRule -Namespace "." -NameServers "192.168.1.1" -DnsSecEnable $false

# Will fail resolution due to AAAA timeout
Resolve-DnsName "domain-name" -Type A

1. DNS Server Configuration

For ZyXEL devices, ensure proper handling of AAAA queries:

# Sample configuration for proper AAAA fallback
dns server
    domain internal
    authoritative
    aaaa-response prefer-ipv4
exit

2. Client-Side Registry Fix

Adjust Windows' DNS resolution behavior via registry:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters]
"DisableParallelAandAAAA"=dword:00000001

3. Network Adapter Configuration

For temporary mitigation until proper DNS fixes are implemented:

netsh interface ipv6 set global randomizeidentifiers=disabled
netsh interface ipv6 set privacy state=disabled

For large deployments, implement these Group Policy settings:

  1. Computer Configuration → Policies → Administrative Templates → Network → DNS Client
    • "Turn off parallel A and AAAA queries" → Enabled
  2. Computer Configuration → Preferences → Windows Settings → Registry
    • Add DisableParallelAandAAAA DWORD (1)

Applications should handle dual-stack scenarios properly. Example C# implementation:

try {
    IPHostEntry hostEntry = Dns.GetHostEntry("domain-name");
    // Prefer IPv4 if available
    IPAddress ip = hostEntry.AddressList.FirstOrDefault(
        a => a.AddressFamily == AddressFamily.InterNetwork) 
        ?? hostEntry.AddressList[0];
} catch (SocketException ex) {
    // Implement fallback logic
    if (ex.SocketErrorCode == SocketError.HostNotFound) {
        // Try with forced A record lookup
        IPHostEntry hostEntry = Dns.GetHostEntry(
            new IPHostEntry { HostName = "domain-name" });
    }
}