Security Changelog

Transparent updates on our infrastructure, security patches, and feature rollouts.

67 updates
MEASUREMENT

Our resolver now truncates empty, not partial

A truncated DNS answer is one a client is required to throw away, so the bytes in it serve nobody except a spoofed victim. Until today we filled that datagram with 1,023 to 1,256 bytes; the large public resolvers send a bare header. We now send one too: fifteen of eighteen census names dropped to 63-71 bytes. The worst case is unchanged at 20.1x, and the reason it is unchanged is the interesting part. Includes a correction: Quad9 does not behave identically to Google.

MEASUREMENT

Checking for an ECH key, and the Windows blind spot

Encrypted Client Hello puts its key in a DNS HTTPS record, so one dig command tells you whether a site supports it. Of eight names checked, three publish a key and cloudflare.com is not among them. Neither DNS tool that ships with Windows can retrieve the record: Resolve-DnsName has no HTTPS type in its enum, and nslookup quietly queries A and AAAA instead. Stock PowerShell can, though, if you build the query by hand - and the answer matches the Linux result byte for byte.

MEASUREMENT

Measured: how much DNS really falls back to TCP

Fifteen minutes of live port-53 traffic on this resolver: 17,424 queries over UDP, 309 over TCP, and five truncated replies out of 17,735. Six public resolvers advertise five different UDP buffer sizes and none uses the 1400 that RFC 9715 recommends. The fallback costs one round trip, 6.4 ms against a resolver 6.31 ms away - a figure dig's own Query time reports as zero, because it does not count the handshake.

MEASUREMENT

Measured: what six DNS transports cost on the wire

Six transports measured with one client against one Quad9 address, so only the transport varies. A cold lookup costs 168 bytes over plain DNS, 1,052 over DNSCrypt, 7,186 over DoT, 7,781 over DoH, 11,769 over DoQ and 12,420 over DoH3 - and the two QUIC transports are the only ones where the client sends more than it receives. Includes a correction: the first version of this measurement compared two programs and blamed the protocols, and its headline was backwards.

POST-MORTEM

Post-mortem: we published a backwards measurement

A measurement published on 27 August said a cold DNSCrypt lookup costs more bytes than a TLS 1.3 handshake. It was live for about two and a half hours and it was backwards, because it compared dnscrypt-proxy against a different client and blamed the protocols. Same client on both arms, DNSCrypt is about seven times cheaper than DoT. What the wrong numbers were, why they survived, and what is withdrawn rather than replaced.

HOW-TO

How-to: the OpenSSH post-quantum key exchange warning

OpenSSH 10.1 warns when a connection negotiates a classical key exchange. The warning comes from the client and describes the server, it is suppressed entirely by pinning KexAlgorithms, and four algorithm names count as post-quantum rather than two. What to change on each side, how to check what was really negotiated, and how the same transition looks in DoH and TLS.

VERIFICATION

How to check your DNS is really encrypted

A leak test shows which resolver answered, not whether the query was encrypted getting there. The per-protocol commands that actually check it, with the real output and the traps that produce a wrong answer.

POST-MORTEM

Post-mortem: Ten Browser Tabs Look More Robotic Than a Bot

Restoring ten tabs puts 61 DNS queries on the wire in 145 milliseconds at a 16 ms cadence. Scored one way that burst reads as human, scored another the identical traffic reads as automated, and the only difference is whether the paired address and HTTPS queries count as one event or two. Measured against 226 real client addresses, plus three corrections to our own account of a false positive - the last of which, added on 27 August, reverses the conclusion the other two reached.

POST-MORTEM

Post-mortem: Banned by Our Own Refusals

Three verified Meta crawlers were hard-banned while asking for /robots.txt. The evidence against them was a 444 our own edge rule had returned to them a moment earlier. A second loop ran the other way: a 59-second ban erased a real user's earned history, and 69 seconds later the same client drew 72 hours. Both loops measured from the durable records, plus the determinism test that separates a client's mistake from your own and how to check a Fail2Ban jail for the same shape.

SECURITY

Measured: why the hardest challenge runs at a few bits and the cheap one needs 26

A new guide measures the two work functions behind browser proof-of-work challenges in the same WebAssembly runtime a browser uses. One SHA-256 probe costs 0.3997 microseconds; one Argon2id probe at 32 MiB costs 154.6 milliseconds - a ratio of about 387,000 to one. That inverts the difficulty settings: a memory-hard tier runs at a handful of bits where the compute tier needs 20 or more, and pushing the compute tier to 26 bits costs a real user a measured median of 19.1 seconds, with a worst run of 64.4 while a rented GPU farm barely notices. A 12-minute flood on 7 August, 67,751 challenges to 923 addresses across 525 networks in 97 countries, produced zero incorrect proofs - and the article is explicit that this shows nobody attempted the work, not that nobody could. Updated 9 August: a fleet of native solvers now answers what the flood could not - a botnet can earn about 0.6 tokens per second per core at four bits, costing it roughly 16 times our verification cost. Two corrections are published with it: one separating the derived compute figures from the measured memory-hard ones, and one retracting the claim that memory-hardness taxes an attacker's parallelism, which measurement reversed. A second flood on 9 August, 1.18 million requests in twenty-four minutes, reproduced the result on three times the scale: 2,036 challenges issued to the swarm and not one attempted, with the machine at a load average of 1.31 on four cores and DNS still answering in 25 to 43 milliseconds. Updated 11 August: the benchmark scripts are published at github.com/Ozy-666/dns-pow-bench with the raw output of four measurement passes. Repeating the run put real error bars on it - the four-bit solve median moved by 69 per cent across three passes of the same measurement, while the per-probe costs that carry the argument reproduced within 2.7 per cent.

POST-MORTEM

Post-mortem: the QUIC Handshake That Failed One Time in Twenty

DoH3 on this resolver failed about one connection in twenty and logged nothing. The cause is in nginx: when a post-quantum ServerHello spans two QUIC Initial packets and one is lost, the loss is detected and the CRYPTO frame is requeued, but the congestion window has collapsed below the bytes in flight and the output loop sends acknowledgements only. The client cannot derive handshake keys without that frame, so it cannot acknowledge anything, so the window never reopens. Reported as nginx/nginx#1616 with a scripted reproduction; a contributor proposed a one-line fix, #1617, which cleared the reported case on a different TLS library than the one used to verify it. Extending the test found the limit of that fix: a certificate flight large enough to fill the 12000-byte initial window deadlocks again, and post-quantum certificates are that large.

MEASUREMENT

We Measured Our Own Four Encrypted DNS Transports

DoH, DoH3, DoT and DoQ all run on this resolver, so the same query can go through each of them and be counted. We measured round trips to a first answer, bytes on the wire per cold lookup, latency percentiles at 2% packet loss, and what the post-quantum key exchange costs. DoQ answers a full round trip before DoT and DoH; DoH3 is also QUIC but hands that round trip back to QUIC address validation, which a packet capture pinned down after we first blamed HTTP/3. Under loss the medians barely move while the tails separate completely: across 300 lookups per transport, both TCP transports land almost exactly one second above their own median at the 99th percentile, while the QUIC transports stop at 310 and 329ms. DoH3 is the transport that fails worst, and tracing that led to a bug in nginx itself, now reported upstream as nginx/nginx#1616 with a scripted reproduction.

POST-MORTEM

Post-mortem: Our Leak Test Was Inventing Leaks

Our DNS leak test reported a phone leaking queries to Google Public DNS. It was not. The probe zone is delegated to a host whose port 53 serves strictly as a recursive resolver, so probe queries ended in SERVFAIL. Quad9 retried 18 times, gave up, and the phone fell back to a secondary resolver 57ms later - which we then recorded as an extra 'leaked' resolver on top of the correct ones. The test itself kept working and kept finding real leaks throughout; the defect added entries rather than removing them, which is why it survived so long.

POST-MORTEM

Post-mortem: One Directive Refused Every HTTP/2 POST

A hardening change on this resolver set nginx's http2_body_preread_size to 16k. Any value below 65535 makes nginx refuse every HTTP/2 request carrying a body - every RFC 8484 DoH POST - for at least five weeks. A new post-mortem documents the code path, the measurement, and a reproduction anyone can run on localhost.

DOCUMENTATION

New Guide: Zero Open Admin Ports

A new how-to documents the pattern this server uses to hide its management plane: the AdGuard Home admin panel and SSH answer two devices over Tailscale and nobody else. Three gates - a localhost bind, an nginx geo allowlist, and a DNS split view from the resolver itself - plus one nftables rule for port 22, each verified from both sides.

SECURITY

Amplification Defence, Part Two: EDNS Clamp, DNS Cookies, and a 4 KB Bug

The two remaining defence layers are live: the public edge truncates UDP answers at 1,232 bytes whatever buffer size a client advertises, and a valid DNS Cookie now exempts a client from rate limiting. Testing the truncation promise end to end also surfaced a silent 4 KB limit in dnscrypt-proxy's TCP path that had been failing large answers for years - fixed.

DOCUMENTATION

Runbook Published: Running a 160-Hour Certificate

The unified certificate behind the site and all encrypted DNS transports lives 160 hours - the condition attached to the only free way to put an IP address in a SAN. The complete production operation is now documented: issuance, ARI renewal, the watchdog and DANE guard scripts published in full, and the failure timeline.

DOCUMENTATION

Runbook Published: The Missing NSEC

A DNS provider served our signed zone's delegation without the NSEC record proving DS absence, and validating resolvers refused the whole subtree with EDE 22. We diagnosed it across six providers, reported it with a one-line reproduction, and the platform-wide fix is now verified. The full account is published as a runbook.

UPDATE

Discovery Answers Now Carry Address Hints (One Less Round Trip)

Every DDR designation the resolver returns for _dns.resolver.arpa now includes ipv4hint=194.180.189.33, on DoH, DoT and DoQ alike. A bootstrapping device can open the encrypted handshake immediately instead of first resolving the target name, saving one round trip at the moment latency is most visible.

DOCUMENTATION

New Reference Guide: Anatomy of a Hardened DNS Zone

A new flagship guide walks through the real dnsdoh.art zone record by record: DNSSEC, DANE on all four transports, the HTTPS record with ECH, DDR discovery, mail lockdown and CAA. Published together with an infrastructure change: the ECH key now rotates monthly, automatically.

DOCUMENTATION

Runbook Published: When a Public Blocklist Bans Googlebot

A crowd-sourced IP blocklist this service imports had listed real Googlebot addresses. The firewall dropped them before nginx ever saw a request, and the site began to fall out of search. The full incident writeup is now published as a guide, with every tool included.

MAJOR UPDATE

Automatic Encrypted DNS Discovery Is Live (Verified DDR)

dnsdoh.art now answers Discovery of Designated Resolvers (RFC 9462) in strict verified mode. A device that knows only the resolver address 194.180.189.33 discovers the encrypted endpoints on its own, and Windows 11 fills in the DoH template automatically.

DOCUMENTATION

Two New Guides: DNS Caching and What Your IP Reveals

Two new evergreen guides: one explains DNS caching and TTL, including why a record can keep resolving to an old address after you change it; the other walks through what an IP address lookup actually shows about you, and what it does not.