DEV Community

Bartosz Osiej
Bartosz Osiej

Posted on Originally published at hartwell-labs.pl

700 US county domains, one DNS record apart from safe

I audited DNS for 700 US county and K-12 government domains this month. Passive lookups only — MX, TXT, CAA. No scanning, no probing, no service enumeration. Every record parsed per RR record and confirmed against at least two independent resolvers.

The numbers:

  • 286 of 700 (41%) publish no DMARC record at all
  • only 97 (14%) are at p=reject
  • 156 are at p=none — detectable, still delivered
  • 227 have SPF ending in ~all — soft-fail, spoofed mail lands anyway
  • 56 out of 700 are actually enforcing (SPF -all + DMARC p=reject)

p=none is not "we have DMARC"

p=none asks receiving servers to watch and report. It does not ask them to refuse anything. Spoofed mail claiming your domain still reaches the inbox — it's just marked, and users are trained to click through the mark. p=reject is what turns detect into do not deliver.

The order that works

_dmarc.example.gov. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.gov"
Enter fullscreen mode Exit fullscreen mode

Start at p=quarantine with a rua= address. Read the aggregate reports until the only senders listed are ones you recognise. Then move to p=reject. Only then tighten SPF from ~all to -all.

Deploying -all before the reports are clean is the single most common way a DMARC rollout gets rolled back — one legitimate sender gets dropped, mail stops, and the record gets deleted.

The audit was wrong the first time

Worth publishing, because it's the part most write-ups skip.

The first pass concatenated each TXT RR set into one string and tested for a v=spf1 prefix. Any leading verification record — MS=, an Apple domain-verification TXT — broke the match, and the domain came back as "no SPF". A second pass used a 3-second resolver timeout under 48-way concurrency and recorded those timeouts as "record absent".

Between them, 22 of the first 82 contact emails carried a finding that wasn't true. All 22 were corrected by email the same day.

The corrected pass: parse per record, confirm with two or more resolvers, and if the answer isn't confirmed, publish nothing rather than guess. A number that gets forwarded to an auditor should survive dig.

Full report

Aggregates, methodology, the list of domains with no DMARC record, and a mailto that hands you your own domain's records as plain text:

https://hartwell-labs.pl/report/

If you run one of these domains: mail me and you get your exact SPF, DMARC, CAA and MX as they resolve today. Free, no call, no pitch — enough to hand to whoever holds your DNS.


Building detection and response for Linux in the meantime — eBPF, no kernel modules, one static binary. If any of your systems run Linux and the mail-gateway view isn't the whole picture: https://hartwell-labs.pl/talus.html

Top comments (0)