How to Prioritize IPv6 DNS Queries

Understanding and controlling how your system prioritizes IPv6 versus IPv4 connections is crucial for optimizing network performance in dual-stack environments. This guide explains the mechanisms that govern address selection and provides practical configurations for prioritizing IPv6 across different operating systems and applications.

Understanding Address Selection

When a hostname has both IPv4 (A record) and IPv6 (AAAA record) DNS entries, your system must decide which protocol to use. This decision involves multiple layers:

DNS Query Order

DNS resolvers typically send both A and AAAA queries simultaneously or with minimal delay. The responses may arrive in any order depending on network conditions.

Address Selection Algorithms

Two key RFCs govern how systems handle dual-stack connections:

RFC 6724 - Default Address Selection

This specification defines how systems sort and select from multiple available addresses. It establishes a policy table with precedence values that determine which address families are preferred. By default, IPv6 addresses receive higher precedence than IPv4.

RFC 8305 - Happy Eyeballs Version 2

Modern applications implement the "Happy Eyeballs" algorithm to provide fast connections while preferring IPv6. The algorithm works as follows:

  1. DNS queries for both A and AAAA records are sent concurrently
  2. If a AAAA response arrives first, IPv6 connection attempt begins immediately
  3. If an A response arrives first, the system waits 50ms (the "Resolution Delay") for the AAAA response
  4. Connection attempts to both address families run in parallel, with IPv6 getting a slight head start
  5. The first successful connection wins

This approach ensures users don't experience delays if IPv6 is broken, while still preferring IPv6 when it works properly.

Linux Configuration

Linux systems use the getaddrinfo() function for address resolution, which can be configured via /etc/gai.conf to control IPv6 preference.

Understanding Default Behavior

By default, Linux follows RFC 6724 with these precedence values:

Precedence  Prefix
50          ::1/128        # Loopback
40          ::/0           # IPv6 default
35          ::ffff:0:0/96  # IPv4-mapped IPv6
30          2002::/16      # 6to4
5           2001::/32      # Teredo
10          fc00::/7       # Unique Local Addresses
1           fec0::/10      # Site-local (deprecated)

The higher the precedence value, the more preferred the address family. The default configuration gives IPv6 (::/0 with precedence 40) priority over IPv4-mapped addresses (::ffff:0:0/96 with precedence 35).

Ensuring IPv6 Priority

To explicitly ensure IPv6 is prioritized, edit /etc/gai.conf:

# Uncomment or add these lines to /etc/gai.conf

# Prefer IPv6 over IPv4
precedence ::ffff:0:0/96  35
precedence ::/0           40

# Full RFC 6724 default table (recommended to include all entries)
precedence ::1/128        50
precedence ::/0           40
precedence 2002::/16      30
precedence ::/96          20
precedence ::ffff:0:0/96  10

Important: When you add any precedence entry to gai.conf, it disables the default rules. You should include the complete policy table to avoid unexpected behavior.

Maximizing IPv6 Preference

For environments where you want to strongly prefer IPv6:

# Edit /etc/gai.conf
precedence ::1/128        50
precedence ::/0           100   # Very high priority for all IPv6
precedence ::ffff:0:0/96  10    # Low priority for IPv4

If you need to prefer IPv4 temporarily for troubleshooting:

# Edit /etc/gai.conf
precedence ::ffff:0:0/96  100   # High priority for IPv4
precedence ::/0           10    # Low priority for IPv6

Applying gai.conf Changes

Changes to /etc/gai.conf take effect immediately for new connections:

# Edit the file
sudo nano /etc/gai.conf

# Test the configuration
getent ahosts www.google.com

The order of addresses returned by getent ahosts reflects your precedence settings.

Windows Configuration

Windows uses a prefix policy table similar to Linux's gai.conf, configured via the netsh command.

Viewing Current Prefix Policies

Display your current IPv6 prefix policy table:

netsh interface ipv6 show prefixpolicies

Output example:

Precedence  Label  Prefix
----------  -----  ------
        50      0  ::1/128
        40      1  ::/0
        35      4  ::ffff:0:0/96
        30      2  2002::/16
         5      5  2001::/32
         3     13  fc00::/7
         1     11  fec0::/10

By default, Windows prefers IPv6 (precedence 40) over IPv4-mapped addresses (precedence 35).

Ensuring IPv6 Priority (Default)

Windows 7 and later versions prefer IPv6 by default. To restore default behavior:

# Reset to default IPv6 preference
netsh interface ipv6 reset

# Or manually set precedence
netsh interface ipv6 set prefixpolicy ::1/128 50 0
netsh interface ipv6 set prefixpolicy ::/0 40 1
netsh interface ipv6 set prefixpolicy ::ffff:0:0/96 35 4
netsh interface ipv6 set prefixpolicy 2002::/16 30 2
netsh interface ipv6 set prefixpolicy 2001::/32 5 5

Maximizing IPv6 Priority

To further emphasize IPv6 preference:

# Increase IPv6 precedence significantly
netsh interface ipv6 set prefixpolicy ::/0 50 1
netsh interface ipv6 set prefixpolicy ::ffff:0:0/96 25 4

If you must prefer IPv4 for compatibility testing:

# Set IPv4 higher precedence than IPv6
netsh interface ipv6 set prefixpolicy ::ffff:0:0/96 46 4
netsh interface ipv6 set prefixpolicy ::/0 35 1

Note: Microsoft recommends adjusting prefix policies rather than disabling IPv6 entirely.

Verifying Windows Changes

Changes take effect immediately. Test with:

# Test DNS resolution order
nslookup www.google.com

# Test connectivity
ping www.google.com

macOS Configuration

macOS follows BSD conventions and generally prefers IPv6 by default when available.

System Defaults

macOS implements RFC 6724 address selection automatically. IPv6 is preferred when:

Limited Configuration Options

macOS doesn't provide a direct equivalent to Linux's gai.conf or Windows' netsh prefix policy commands. The system-level address selection is built into the network stack.

Testing Address Selection

# Check which protocol is used
dscacheutil -q host -a name www.google.com

# Test IPv6 connectivity
ping6 www.google.com

# Force IPv6 in curl
curl -6 https://ipv6.icanhazip.com

Network Service Order

While you cannot directly configure address precedence, you can influence behavior by setting network service order in System Preferences > Network > Set Service Order.

Browser-Specific Behavior

Modern browsers implement Happy Eyeballs (RFC 8305) but with varying implementations.

Firefox

Firefox has built-in IPv6 support enabled by default:

Configuration via about:config:

  1. Type about:config in the address bar
  2. Search for network.dns.disableIPv6
  3. Default value: false (IPv6 enabled and preferred)

Note: Recent Firefox versions use "fast fallback" - if IPv6 connections are slower than one-third of a second, IPv4 is attempted in parallel. This behavior cannot be disabled via settings.

Google Chrome

Chrome implements Happy Eyeballs with automatic protocol selection:

Chrome will prefer IPv6 if:

Safari

Safari follows macOS system defaults and implements address selection according to the underlying network stack. There are no Safari-specific IPv6 preference controls.

Microsoft Edge

Edge on Windows follows the OS prefix policy table and implements Happy Eyeballs similar to Chrome.

Application-Level Considerations

Applications that don't implement Happy Eyeballs rely entirely on the OS-level address selection from getaddrinfo().

Command-Line Tools

Many command-line tools provide flags to force protocol selection:

# curl - force IPv6
curl -6 https://api6.ipify.org

# wget - prefer IPv6
wget --prefer-family=IPv6 https://example.com

# ssh - force IPv6
ssh -6 user@example.com

# ping - IPv6 only
ping6 google.com

Programming Languages

Applications can influence address selection in code:

Python:

import socket

# Get all addresses (respects gai.conf)
addrs = socket.getaddrinfo('www.google.com', 443)

# Filter for IPv6 only
ipv6_addrs = [a for a in addrs if a[0] == socket.AF_INET6]

Node.js:

const dns = require('dns');

// Set IPv6 preference
dns.setDefaultResultOrder('ipv6first');

// Or use options per lookup
dns.lookup('www.google.com', { family: 6 }, callback);

Docker and Containers

Docker requires explicit IPv6 configuration:

// /etc/docker/daemon.json
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"
}

Restart Docker after configuration changes.

DNS Server Configuration

The DNS server communication itself can be prioritized for IPv6.

Specifying IPv6 DNS Servers

Linux (systemd-resolved):

# Edit /etc/systemd/resolved.conf
[Resolve]
DNS=2001:4860:4860::8888 2001:4860:4860::8844
FallbackDNS=8.8.8.8 8.8.4.4

Windows:

# Set IPv6 DNS servers
netsh interface ipv6 set dns "Ethernet" static 2001:4860:4860::8888
netsh interface ipv6 add dns "Ethernet" 2001:4860:4860::8844 index=2

macOS:

Configure via System Preferences > Network > Advanced > DNS and add IPv6 DNS server addresses.

Router Advertisement DNS

For SLAAC environments, routers can advertise DNS servers via Router Advertisement (RA) messages using RDNSS (Recursive DNS Server) option.

Testing and Verification

After configuring IPv6 prioritization, verify your setup works correctly.

Basic Connectivity Tests

# Linux: Test which protocol is used
getent ahosts www.google.com

# Check resolved addresses in order
nslookup www.google.com

# Test IPv6 connectivity
ping6 -c 4 www.google.com

# Trace routing
traceroute6 www.google.com

Protocol Detection

# Check your public IP addresses
curl https://api.ipify.org      # Should return IPv4
curl https://api6.ipify.org     # Should return IPv6
curl https://api64.ipify.org    # Returns whichever protocol is used

Comprehensive IPv6 Testing

Visit test-ipv6.run for comprehensive testing. The site evaluates:

The testing runs entirely in your browser and provides real-time diagnostics, making it ideal for verifying that your IPv6 prioritization settings work as expected.

Monitoring Protocol Usage

# Linux: Monitor active IPv6 connections
ss -6 -t

# Windows: Display IPv6 connections
netstat -an -p tcpv6

# View connection statistics
netstat -s -p ipv6

Troubleshooting

IPv6 Preferred but Connections Fail

If your system prefers IPv6 but connections are slow or failing:

  1. Test basic IPv6 connectivity:

    ping6 2001:4860:4860::8888
    
  2. Check for broken IPv6 - Visit test-ipv6.run and check for "broken IPv6" status (score 0/10 with red indicators)

  3. Verify firewall rules - Ensure ICMPv6 and TCP/UDP over IPv6 are allowed

  4. Check router configuration - Confirm your gateway supports IPv6 and has proper upstream connectivity

Dual-Stack Test Failures

If IPv4 and IPv6 work individually but dual-stack tests fail:

Verifying Happy Eyeballs

To confirm Happy Eyeballs is working:

  1. Visit a dual-stack website (www.google.com)
  2. Open browser developer tools (F12)
  3. Check Network tab for connection timing
  4. IPv6 should be attempted first with IPv4 as fallback

Best Practices

For most users wanting to prioritize IPv6:

  1. Keep OS defaults - Modern operating systems already prefer IPv6
  2. Ensure IPv6 connectivity works - Priority doesn't help if IPv6 is broken
  3. Use test-ipv6.run regularly - Monitor your IPv6 readiness score
  4. Don't disable IPv4 - Dual-stack is the recommended deployment model

Enterprise Environments

For organizations deploying IPv6:

  1. Use monitoring - Track IPv4 vs IPv6 usage across your network
  2. Configure policy centrally - Use Group Policy (Windows) or configuration management tools (Linux)
  3. Test application compatibility - Ensure all applications support IPv6
  4. Educate users - Many issues stem from misunderstanding dual-stack behavior

Security Considerations

Conclusion

Prioritizing IPv6 DNS queries involves multiple layers - from DNS resolution timing to address selection algorithms to application-level connection handling. Modern operating systems and browsers generally prefer IPv6 by default when both protocols are available, implementing smart fallback mechanisms like Happy Eyeballs to ensure optimal user experience.

For most users, the default configurations are optimal. System administrators can fine-tune behavior using /etc/gai.conf on Linux or netsh interface ipv6 commands on Windows to influence address selection precedence. However, the key to successful IPv6 prioritization isn't just configuration - it's ensuring your IPv6 connectivity is reliable and performant.

Always verify your configuration changes with comprehensive testing tools like test-ipv6.run, which provides detailed diagnostics of your dual-stack connectivity, protocol preference, and overall IPv6 readiness. A high IPv6 readiness score (9-10/10) indicates that your system is correctly prioritizing and successfully using IPv6 connections.