Advanced IPv6 Troubleshooting: dig, ping6, traceroute6, and curl -6 for Network Engineers
Why does your AAAA record resolve correctly from one recursive resolver but return SERVFAIL from another, even though both query the same authoritative server? The answer usually involves DNSSEC validation, EDNS0 buffer sizes, or fragmented UDP responses that get dropped by middleboxes. These are the kinds of IPv6 problems that do not show up in basic connectivity checks and require protocol-level investigation to diagnose.
This guide is for engineers who already understand IPv6 addressing, know the difference between link-local and global unicast, and have run ping6 before. We are going deeper: advanced dig options for dissecting DNS behavior, traceroute6 techniques for identifying asymmetric routing and PMTU black holes, curl -6 patterns for isolating TLS and HTTP issues on the IPv6 path, and openssl commands for validating certificate chains over IPv6 connections specifically. Combined with automated monitoring from UptyBots, these techniques give you both the diagnostic depth for troubleshooting and the continuous coverage for production.
Advanced DNS Diagnostics with dig
Basic dig AAAA example.com +short tells you whether an AAAA record exists. Advanced dig usage tells you why resolution fails, where it fails, and what the resolver sees that your browser does not show you.
Tracing the Full Resolution Chain
dig AAAA example.com +trace
The +trace flag makes dig perform iterative resolution from the root, walking down through the TLD servers to your authoritative nameservers. This bypasses your local recursive resolver entirely, showing you the exact delegation chain. Each step is printed with the server that responded:
. 518400 IN NS a.root-servers.net.
com. 172800 IN NS a.gtld-servers.net.
example.com. 86400 IN NS ns1.example.com.
example.com. 300 IN AAAA 2001:db8::1
If the trace succeeds but a normal query through your resolver fails, the problem is at the resolver level (caching, DNSSEC validation, or network connectivity between the resolver and your authoritative server).
Checking DNSSEC Validation
dig AAAA example.com +dnssec +cd
The +dnssec flag requests DNSSEC records (RRSIG, DNSKEY, DS) alongside the answer. The +cd flag (Checking Disabled) tells the resolver to skip validation and return the answer anyway. If a query with +cd succeeds but without +cd fails (SERVFAIL), you have a DNSSEC validation problem.
Common DNSSEC issues that break AAAA resolution:
- Expired RRSIG: The signature on your AAAA record set has expired. Validating resolvers reject the response. Non-validating resolvers still work, creating a split where some users can resolve your domain and others cannot.
- Missing DS record at parent: Your zone is signed but the DS (Delegation Signer) record at the parent zone (.com, .net, etc.) is missing or incorrect. Resolvers that perform top-down DNSSEC validation fail because the chain of trust is broken.
- Algorithm mismatch: Your zone uses a DNSSEC signing algorithm that the resolver does not support. This is rare with modern algorithms (ECDSAP256SHA256, Algorithm 13) but can happen with older or obscure algorithms.
Testing EDNS0 and Response Size
dig AAAA example.com +bufsize=512
dig AAAA example.com +bufsize=4096
EDNS0 (Extension Mechanisms for DNS) allows DNS responses larger than the traditional 512-byte UDP limit. The +bufsize option sets the advertised EDNS0 buffer size. If a query with +bufsize=4096 succeeds but +bufsize=512 triggers truncation (TC flag set, falling back to TCP), and TCP DNS (port 53) is blocked by a middlebox, you have found a common cause of intermittent DNS failures.
IPv6 is particularly susceptible to this because AAAA responses combined with DNSSEC signatures are often larger than IPv4-only responses. A firewall or NAT device that silently drops DNS UDP packets larger than 512 bytes will break AAAA resolution while A records (smaller responses) continue to work.
Querying Specific Nameservers over IPv6
dig AAAA example.com @2001:4860:4860::8888
dig AAAA example.com @2606:4700:4700::1111
By specifying the resolver's IPv6 address (Google DNS and Cloudflare DNS respectively), you force dig to communicate with the resolver over IPv6. If this fails but querying the same resolver over IPv4 (@8.8.8.8) succeeds, the problem is IPv6 connectivity between your machine and the resolver, not DNS content.
Checking for AAAA Record Inconsistency Across Authoritative Servers
dig AAAA example.com @ns1.example.com +short
dig AAAA example.com @ns2.example.com +short
Query each authoritative nameserver directly and compare results. If they return different AAAA records (or one returns a record and the other does not), your zone transfer or DNS synchronization is broken. This causes intermittent resolution failures depending on which authoritative server the recursive resolver happens to query.
Advanced ping6 Techniques
Beyond basic reachability, ping6 can reveal PMTU issues, kernel-level rate limiting, and routing instability.
Detecting Path MTU Black Holes
ping6 -s 1452 -M do -c 5 example.com
The -s 1452 flag sets the ICMPv6 payload size to 1452 bytes (which, with the 8-byte ICMPv6 header and 40-byte IPv6 header, totals 1500 bytes, the standard Ethernet MTU). The -M do flag sets the "Don't Fragment" bit (technically, IPv6 never fragments at intermediate routers, but this tells the sending stack not to perform source fragmentation).
If packets of this size fail but smaller packets succeed, there is a link along the path with an MTU smaller than 1500 bytes (common with tunnels, PPPoE, VPN encapsulation). Normally, the router with the smaller MTU sends back an ICMPv6 Packet Too Big (type 2) message, and your OS reduces the path MTU accordingly. But if that ICMPv6 message is blocked by a firewall along the return path, your OS never learns about the MTU restriction. Large packets silently disappear. This is a PMTU black hole.
Symptoms in production: small HTTP responses (health check endpoints, JSON APIs) work fine over IPv6. Large responses (full HTML pages, image transfers, large API payloads) hang or timeout. The TCP connection establishes, the small initial packets go through, but once the TCP window scales up and segments exceed the path MTU, packets are dropped with no ICMPv6 feedback.
Testing with Different Packet Sizes
for size in 100 500 1000 1200 1400 1452; do
echo "Size: $size"
ping6 -s $size -M do -c 3 -W 2 example.com 2>&1 | tail -1
done
This script tests multiple packet sizes to find the exact MTU threshold where packets start failing. If 1200 succeeds but 1400 fails, the path MTU is somewhere between 1240 and 1440 bytes (accounting for headers). This pinpoints a tunnel or encapsulation point on the path.
Monitoring Jitter and Packet Loss Patterns
ping6 -c 100 -i 0.2 example.com
Send 100 pings at 200ms intervals (5 per second). Look at the summary statistics:
- Packet loss percentage: Any loss above 0% on a wired network indicates congestion, rate limiting, or a flapping route.
- RTT standard deviation (mdev): Low mdev (under 2 ms) indicates a stable path. High mdev (10+ ms) indicates jitter, which is often caused by queue buildup at a congested hop or inconsistent routing (packets taking different paths on different iterations).
- RTT pattern: If RTT slowly increases over the test, the path is becoming congested. If RTT alternates between two distinct values, packets may be taking two different routes (ECMP with asymmetric path lengths).
Advanced traceroute6 Analysis
Using TCP Traceroute for Firewall Traversal
sudo traceroute6 -T -p 443 example.com
Standard traceroute6 uses UDP packets (or ICMPv6 on some systems). Many firewalls drop UDP traceroute probes, causing hops to appear as * * * even when they are functional. The -T flag switches to TCP SYN probes, which are more likely to pass through firewalls because they resemble legitimate connection attempts. Targeting port 443 specifically tests the path that HTTPS traffic takes.
Detecting Asymmetric Routing
traceroute6 example.com
# Then ask the server admin to run:
traceroute6 [your-ipv6-address]
Compare the forward path (you to server) with the reverse path (server to you). In IPv6 networks, asymmetric routing is common because different transit providers may be preferred for different directions based on BGP policy. A problem on the reverse path (server to you) causes your checks to fail even though the server received and processed your request.
If you do not have access to the server, you can infer asymmetric routing from ping6 results: if the request is definitely reaching the server (you can see it in server logs) but the reply is not reaching you, the return path is broken.
Identifying Tunnel Endpoints
traceroute6 -I example.com
Look for hops where the IPv6 address belongs to a tunnel broker (e.g., Hurricane Electric's 2001:470::/32 prefix) or where the hostname includes "tun," "6in4," "6to4," or "teredo." These indicate that IPv6 traffic is being tunneled over IPv4, which adds latency and introduces a dependency on the tunnel broker's availability.
If you see tunnel hops in the path to your own server, it means either your server's hosting provider or an upstream transit provider is using tunneled IPv6 instead of native. Native IPv6 is preferred for performance and reliability. Contact your provider about native IPv6 support.
Using Paris Traceroute for ECMP Analysis
paris-traceroute6 example.com
Classic traceroute6 varies the destination port or flow label for each probe, which causes ECMP (Equal-Cost Multi-Path) routers to send probes along different paths. This produces misleading output where hops appear to "cross" or where the same hop shows up at multiple positions. Paris traceroute keeps the flow identifier constant, ensuring all probes follow the same ECMP path. This gives you an accurate view of the actual path your traffic takes.
Install it separately: apt install paris-traceroute on Debian/Ubuntu.
Advanced curl -6 Diagnostics
Full Timing Breakdown
curl -6 -o /dev/null -s -w "\
dns: %{time_namelookup}s\n\
connect: %{time_connect}s\n\
tls: %{time_appconnect}s\n\
firstbyte: %{time_starttransfer}s\n\
total: %{time_total}s\n\
http_code: %{http_code}\n\
remote_ip: %{remote_ip}\n" https://example.com
This outputs a timing breakdown for the IPv6 request:
- dns (time_namelookup): Time to resolve the AAAA record. If this is slow (200+ ms), your DNS infrastructure needs attention.
- connect (time_connect): Time from resolution to TCP connection established. Subtract
time_namelookupto get the pure TCP handshake RTT over IPv6. - tls (time_appconnect): Time to complete the TLS handshake. Subtract
time_connectfor the pure TLS overhead. TLS 1.3 should add roughly one RTT; TLS 1.2 adds two. - firstbyte (time_starttransfer): Time to receive the first byte of the HTTP response. Subtract
time_appconnectfor server processing time. - total (time_total): Total request time including response body transfer.
- remote_ip: Confirms which IPv6 address was actually used. Essential when the domain has multiple AAAA records.
Run the same command without -6 to get IPv4 timings. Compare each phase. If the TCP connect time over IPv6 is 3x the IPv4 time, IPv6 routing is suboptimal. If the TLS time is significantly different, there may be a server configuration issue (different TLS settings on the IPv6 virtual host). If the server processing time (firstbyte minus tls) differs, the application may be handling IPv6 and IPv4 connections differently.
Testing Happy Eyeballs Behavior
curl -v --happy-eyeballs-timeout-ms 150 https://example.com 2>&1 | grep "Connected to"
Modern clients implement RFC 8305 (Happy Eyeballs v2), which races IPv6 and IPv4 connection attempts with a head start for IPv6 (typically 250 ms). If IPv6 does not connect within the head start period, IPv4 starts in parallel. Whichever connects first wins.
If you see curl connecting over IPv4 even though AAAA records exist, your IPv6 path is slower than the happy-eyeballs timeout. This means real users with modern browsers are silently falling back to IPv4, and your IPv6 infrastructure has a latency problem that is being masked by client-side fallback behavior. Your users are not affected (yet), but you are not getting the benefits of IPv6 either, and if IPv4 develops a problem, the fallback that currently saves users will not be available.
Testing Specific Addresses with SNI
curl -6 -v --resolve example.com:443:[2001:db8::1] https://example.com
curl -6 -v --resolve example.com:443:[2001:db8::2] https://example.com
When your domain resolves to multiple IPv6 addresses (CDN, load balancer, anycast), test each one individually. One address might have a misconfigured TLS certificate, a different application version, or be located in a region with different routing characteristics.
Detecting Content Differences
diff <(curl -4 -s https://example.com | head -50) <(curl -6 -s https://example.com | head -50)
Compare the actual content served over IPv4 vs IPv6. If the responses differ, your CDN or load balancer may be routing IPv4 and IPv6 traffic to different origins. This can happen when IPv4 traffic goes through a CDN edge cache but IPv6 traffic bypasses it and hits the origin directly (or vice versa).
Advanced TLS Validation over IPv6
Full Certificate Chain Inspection
openssl s_client -connect [2001:db8::1]:443 -servername example.com -showcerts 2>/dev/null | openssl x509 -noout -text | grep -E "Issuer:|Subject:|Not After|DNS:"
This connects to a specific IPv6 address, presents the SNI hostname, retrieves the certificate chain, and extracts the key fields: issuer, subject, expiration, and SAN (Subject Alternative Names). Run the same command against the IPv4 address and compare. The certificates should be identical. If they are not, your server is using different certificates for IPv4 and IPv6 connections, which indicates a virtual host misconfiguration.
Testing OCSP Stapling over IPv6
openssl s_client -connect [2001:db8::1]:443 -servername example.com -status 2>/dev/null | grep -A 5 "OCSP Response"
The -status flag requests the OCSP stapled response. If the server returns an OCSP response over IPv4 but not over IPv6, the TLS configuration differs between address families. Some web server configurations only enable OCSP stapling on the IPv4 listening directive and forget to add it to the IPv6 one.
Missing OCSP stapling over IPv6 means clients have to fetch the OCSP response themselves, adding latency and creating a dependency on the CA's OCSP responder being reachable from the client's network. If the OCSP responder is unreachable (or slow), some clients may soft-fail (accept the certificate anyway) while others hard-fail (reject it), creating inconsistent behavior.
Checking TLS Protocol and Cipher Differences
# IPv6
openssl s_client -connect [2001:db8::1]:443 -servername example.com 2>/dev/null | grep -E "Protocol|Cipher"
# IPv4
openssl s_client -connect 93.184.216.34:443 -servername example.com 2>/dev/null | grep -E "Protocol|Cipher"
If the negotiated protocol or cipher suite differs between IPv4 and IPv6 connections, the server has separate TLS configurations for each address family. In Nginx, this happens when the ssl_protocols and ssl_ciphers directives appear in the listen 443 ssl block but not in the listen [::]:443 ssl block (or vice versa). In Apache, separate <VirtualHost [::]:443> blocks may have different SSLProtocol settings.
Systematic Troubleshooting Workflow
When UptyBots alerts you to an IPv6 failure, follow this protocol-level workflow to isolate the problem:
-
DNS layer: Run
dig AAAA example.com +trace. Does the AAAA record exist? Does it point to the correct address? Is DNSSEC validation succeeding? Query multiple resolvers (@8.8.8.8,@1.1.1.1,@9.9.9.9) over both IPv4 and IPv6 to isolate resolver-specific issues. -
Network layer: Run
ping6 -c 10 example.com. Is the host reachable? What is the latency and packet loss? Runping6 -s 1452 -M doto test for PMTU issues. If ping fails, runtraceroute6 -T -p 443to find where packets are being dropped. -
Transport layer: Run
curl -6 -o /dev/null -s -w "%{time_connect}\n" https://example.com. Does the TCP handshake complete? If connect time is very high, the issue is network latency or congestion. If it times out, the server is not accepting IPv6 connections on that port. -
TLS layer: Run
openssl s_client -connect [address]:443 -servername example.com. Does the handshake complete? Is the certificate valid? Is the chain complete? Compare with IPv4 to identify configuration differences. -
Application layer: Run
curl -6 -v https://example.com. What HTTP status code do you get? Does the response body look correct? Is the response time acceptable? Compare withcurl -4. -
PMTU layer: If large responses fail but small ones succeed, test with
ping6 -sat various sizes. Check that ICMPv6 type 2 (Packet Too Big) is not being blocked by firewalls on any hop.
Firewall Rules That Break IPv6
The most common category of IPv6-specific failures is firewall misconfiguration. Engineers who are experienced with IPv4 firewall rules sometimes apply the same thinking to IPv6 without accounting for protocol differences.
ICMPv6 Is Not Optional
In IPv4, blocking ICMP is a debatable security practice (it hides your server from ping sweeps at the cost of disabling PMTU discovery). In IPv6, blocking ICMPv6 is catastrophic. ICMPv6 handles:
- Neighbor Discovery (types 133-137): The IPv6 equivalent of ARP. Without it, hosts on the same link cannot discover each other's MAC addresses. Blocking these breaks all local IPv6 communication.
- Packet Too Big (type 2): Path MTU Discovery. Without it, large packets are silently dropped as described in the PMTU section above.
- Destination Unreachable (type 1): Tells the sender that a destination is unreachable. Without it, connections to dead hosts hang until timeout instead of failing immediately.
- Echo Request/Reply (types 128-129): Ping. Useful for diagnostics but the least critical of the four.
At minimum, allow ICMPv6 types 1, 2, 3, 4, 128, 129, and 133-137. Most IPv6 security guides recommend allowing all ICMPv6 types from link-local sources and types 1-4 and 128-129 from global sources.
ip6tables vs iptables
On Linux, iptables rules only affect IPv4 traffic. IPv6 traffic is governed by ip6tables (or nftables with ip6 family). A common mistake is configuring iptables rules to allow HTTP traffic but forgetting to create matching ip6tables rules. The result: IPv4 HTTP works, IPv6 HTTP is blocked.
# Check IPv4 rules
sudo iptables -L -n | grep -E "443|80"
# Check IPv6 rules
sudo ip6tables -L -n | grep -E "443|80"
With nftables, you can create rules in the inet family that apply to both IPv4 and IPv6, avoiding this dual-maintenance problem.
Web Server Configuration Pitfalls
Nginx: Separate Listen Directives
# Correct: both IPv4 and IPv6
listen 443 ssl;
listen [::]:443 ssl;
# Incorrect: IPv4 only
listen 443 ssl;
# (missing IPv6 listen directive)
On some systems, listen 443 ssl binds to both IPv4 and IPv6 (if net.ipv6.bindv6only=0). On others, it binds only to IPv4. The behavior depends on the OS default for IPV6_V6ONLY socket option. Explicitly specifying both directives removes the ambiguity.
Apache: Separate VirtualHost Blocks
# Both protocols in one block
<VirtualHost *:443>
# handles both IPv4 and IPv6
</VirtualHost>
# Or explicit per-protocol blocks
<VirtualHost 93.184.216.34:443>
# IPv4 only
</VirtualHost>
<VirtualHost [2001:db8::1]:443>
# IPv6 only - must have identical SSL config
</VirtualHost>
If you use explicit IP-based VirtualHost blocks, the IPv6 block must have all the same SSL directives (SSLEngine, SSLCertificateFile, SSLCertificateKeyFile, SSLProtocol, etc.) as the IPv4 block. A missing directive in the IPv6 block causes different TLS behavior per protocol.
Comparing Manual Results with Automated Monitoring
Manual diagnostics give you deep, on-demand insight. Automated monitoring gives you continuous, multi-location coverage. Here is how they complement each other at the protocol level:
| Capability | Manual (dig, ping6, curl, openssl) | Automated (UptyBots) |
|---|---|---|
| PMTU black hole detection | Yes (ping6 -s with -M do) | Indirectly (detects timeouts on large responses) |
| DNSSEC validation debugging | Yes (dig +dnssec +cd) | Detects resolution failures, not DNSSEC specifics |
| Asymmetric routing analysis | Yes (traceroute6 from both ends) | Multi-location checks reveal path-specific failures |
| TLS config parity checking | Yes (openssl s_client per address) | Detects certificate expiry and chain issues |
| Continuous coverage | No (point-in-time only) | Yes (every 1-5 minutes, 24/7) |
| Multi-location perspective | Limited (your networks + VPS) | Multiple geographic monitoring locations |
| Alerting | None | Email, Telegram, webhooks |
| Historical trend analysis | Only if you script and store results | Built-in charts and data retention |
The workflow: UptyBots detects an IPv6 failure and alerts you. You open a terminal and run the diagnostic commands from this guide to identify the root cause. You fix the issue. UptyBots confirms recovery. The manual tools are for investigation; the automated monitoring is for detection and verification.
IPv6 Diagnostics Checklist for Network Engineers
- AAAA records consistent across all authoritative nameservers
- DNSSEC signatures valid and not expiring within 24 hours
- DNS responses not truncated due to EDNS0 buffer size issues
- ping6 succeeds with default and maximum-MTU packet sizes
- traceroute6 shows no tunnel hops on paths that should be native
- curl -6 timing comparable to curl -4 timing (within 2x)
- TLS certificate chain identical over IPv4 and IPv6
- OCSP stapling enabled on both IPv4 and IPv6 listen directives
- ICMPv6 types 1-4, 128-129, and 133-137 allowed in firewall
- ip6tables/nf_tables rules mirror iptables rules for HTTP/HTTPS
- Web server listen directives explicitly include [::] for IPv6
- Automated IPv6 monitoring configured in UptyBots
For background on why monitoring both protocols separately matters, see our post on why monitoring both IPv4 and IPv6 matters for modern websites. To understand what happens when IPv6-only users cannot reach your site, read about the hidden downtime you might miss from IPv6-only users. You can also estimate the financial impact of IPv6-specific outages using our Downtime Cost Calculator.
See setup tutorials or get started with UptyBots monitoring today.