During routine DNS maintenance where we temporarily redirected CNAME records to alternate servers, we encountered a puzzling scenario. While traditional tools like nslookup
showed correct resolution across our primary and secondary DNS servers, third-party verification services like whatsmydns.com consistently reported "error: token mismatch" across all polled DNS servers.
A token mismatch in DNS validation typically occurs when:
- DNS query signatures don't match expected cryptographic tokens
- There's a mismatch in DNSSEC validation chains
- Intermediate DNS resolvers modify query packets
Example of how to verify DNSSEC validation:
dig example.com +dnssec +multiline
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
1. DNSSEC Validation Issues:
When maintaining DNS records, temporary inconsistencies between DS records at the registrar and DNSKEY records in your zone can trigger token validation failures.
2. DNS Load Balancing Systems:
Some global DNS verification services implement custom token-based validation that may conflict with:
# Sample BIND zone file showing proper TTL settings
$TTL 3600
@ IN SOA ns1.example.com. admin.example.com. (
2023081501 ; serial
3600 ; refresh
900 ; retry
604800 ; expire
3600 ) ; minimum
When encountering token mismatches:
# Check for DNSSEC validation chain
delv example.com +vtrace
# Verify DNS glue records
dig +trace example.com NS
# Inspect TTL values
dig example.com ANY
In our case, the solution involved:
- Standardizing TTL values before maintenance (minimum 1 hour)
- Coordinating with our registrar to temporarily relax DNSSEC requirements
- Implementing phased CNAME updates using weighted records:
; AWS Route53 weighted record example
backend IN CNAME 10 server1.elb.amazonaws.com
backend IN CNAME 10 server2.elb.amazonaws.com
Developers should:
- Maintain DNS change logs with precise timestamps
- Implement canary DNS updates using health checks
- Consider DNS propagation testing tools like:
# Python DNS verification snippet
import dns.resolver
answers = dns.resolver.resolve('example.com', 'CNAME')
for rdata in answers:
print('CNAME Target:', rdata.target)
During our routine DNS maintenance, we encountered a puzzling scenario where whatsmydns.com
consistently reported "error: token mismatch" despite proper CNAME propagation confirmed via nslookup
. This discrepancy highlights an important distinction between raw DNS resolution and third-party monitoring tools.
Many DNS checking services implement token-based validation to:
- Prevent DNS cache poisoning attacks
- Verify request authenticity
- Track propagation paths
A typical verification flow looks like:
// Pseudocode for DNS verification token system function generateVerificationToken(domain) { const salt = crypto.randomBytes(16); return hash(domain + salt + timestamp); } function validateDNSRequest(request) { if (request.token !== expectedToken) { throw "error: token mismatch"; } return performDNSCheck(request.domain); }
The token mismatch typically occurs when:
- DNS changes are mid-propagation
- Intermediate DNS servers haven't synchronized
- The checking service's validation tokens expire
When troubleshooting, always combine multiple verification approaches:
# Bash script for comprehensive DNS verification #!/bin/bash domain="example.com" expected_cname="newserver.example.net" # Method 1: Standard nslookup nslookup -query=CNAME $domain # Method 2: Dig with trace dig +trace CNAME $domain # Method 3: Check TTL values dig +nocmd +noall +answer +ttlid CNAME $domain # Method 4: Cross-validate with public DNS for resolver in 1.1.1.1 8.8.8.8 9.9.9.9; do echo "Checking $resolver:" dig @$resolver CNAME $domain done
Token mismatches are usually harmless when:
- Other verification methods confirm proper propagation
- The error persists < 24 hours during changes
Investigate immediately if:
- All verification methods disagree
- Mismatches persist beyond TTL expiration
- Actual service availability is affected
For critical infrastructure, consider implementing your own checker:
// Node.js DNS verification module const dns = require('dns'); const crypto = require('crypto'); class DNSChecker { constructor(domain) { this.domain = domain; this.verificationToken = this.generateToken(); } generateToken() { return crypto.createHash('sha256') .update(${this.domain}:${Date.now()}) .digest('hex'); } async verifyCNAME(expected) { return new Promise((resolve) => { dns.resolveCname(this.domain, (err, records) => { if (err) return resolve({valid: false, error: err}); resolve({ valid: records.includes(expected), records: records, token: this.verificationToken }); }); }); } }