Intermediate 10 min DNS 1

FORMERR — Malformed DNS Query

Gejala

- `dig example.com` returns `status: FORMERR` against certain nameservers
- The same query succeeds against other resolvers (Google 8.8.8.8, Cloudflare 1.1.1.1)
- Applications report 'DNS format error' or fail to resolve the domain
- Packet captures show EDNS OPT record in the query but FORMERR in the reply
- BIND debug logs show 'query (cache) 'example.com/ANY/IN' denied' with FORMERR response

Penyebab Utama

  • DNS server does not support EDNS0 extensions and returns FORMERR for EDNS queries
  • Malformed DNS packet produced by a buggy DNS client library on the application side
  • Query name exceeds 253 characters or a single label exceeds 63 characters (RFC 1035 limit)
  • Invalid query type or class in the DNS request (e.g., QTYPE=0 which is reserved)
  • Firewall or middlebox mangling DNS packets in transit, corrupting the wire format

Diagnosis

**Step 1 — Confirm FORMERR and isolate the failing nameserver**

```bash
# Standard EDNS query:
dig @ns1.example.com example.com A
# status: FORMERR = server rejected the query format

# Compare against a public resolver:
dig @8.8.8.8 example.com A
# If public DNS works, the issue is with the specific nameserver
```

**Step 2 — Diagnose EDNS0 incompatibility**

```bash
# Disable EDNS0 to check if that resolves the FORMERR:
dig @ns1.example.com example.com A +noedns
# If +noedns succeeds → the server is EDNS0-unaware

# Also try with reduced EDNS buffer size:
dig @ns1.example.com example.com A +bufsize=512
```

**Step 3 — Check query name length**

```bash
# DNS name max 253 characters, each label max 63 characters:
echo -n 'very-long-subdomain.example.com' | wc -c
# Must be < 254 characters total

# Check label lengths:
python3 -c "
name = 'very-long-subdomain.example.com'
labels = name.split('.')
print([(l, len(l)) for l in labels])
# Each label must be <= 63 characters
"
```

**Step 4 — Test for firewall packet mangling**

```bash
# Capture DNS traffic to look for corruption:
sudo tcpdump -i eth0 -n 'port 53' -w /tmp/dns.pcap
# Query the NS in another terminal:
dig @ns1.example.com example.com A
# Analyse in Wireshark — look for malformed OPT records or truncated packets
```

**Step 5 — Check DNS software version on the server**

```bash
# Query the version (if BIND allows it):
dig @ns1.example.com version.bind TXT CHAOS
# BIND versions < 9.4 have known EDNS0 bugs
# If version is hidden (refused), check with the server admin
```

Resolusi

**Fix 1 — Disable EDNS0 as a workaround for old servers**

```bash
# BIND resolver — add edns-udp-size workaround for specific servers:
# /etc/named.conf
server ns1.example.com {
edns no; # disable EDNS0 for this upstream
};

# systemd-resolved — all queries go without EDNS by default on old distros
# Check: systemd-resolve --status | grep 'DNS Servers'
```

**Fix 2 — Update the nameserver software**

```bash
# Update BIND9 on the nameserver:
sudo apt update && sudo apt install -y bind9

# Or replace with a modern alternative:
sudo apt install -y unbound # recommended recursive resolver
```

**Fix 3 — Fix firewall to stop mangling DNS packets**

```bash
# iptables — disable DNS packet inspection (conntrack) that corrupts EDNS:
sudo iptables -t raw -A OUTPUT -p udp --dport 53 -j CT --notrack
sudo iptables -t raw -A OUTPUT -p tcp --dport 53 -j CT --notrack

# Or disable DNSSEC-stripping in some consumer routers:
# Access router admin → DNS settings → disable 'DNS rebind protection'
```

**Fix 4 — Fix malformed client query**

```python
# Python — use dnspython with explicit EDNS options:
import dns.resolver
resolver = dns.resolver.Resolver()
resolver.use_edns(0, 0, 1232) # EDNS version 0, no flags, 1232 byte payload
answer = resolver.resolve('example.com', 'A')
```

Pencegahan

- Use modern, RFC-compliant DNS server software (BIND 9.16+, Unbound 1.13+, PowerDNS 4.5+)
- Test DNS queries with EDNS0 enabled and disabled during any nameserver migration
- Validate domain name lengths programmatically before sending DNS queries in applications
- Audit firewall rules for DNS traffic — disable stateful inspection on UDP port 53 if it causes issues
- Include EDNS compatibility tests in your DNS monitoring alert suite

Kode Status Terkait

Istilah Terkait