Mail: spf=temperror on a large share of inbound mail, embedded DNS drops concurrent queries
-
I went looking for why a spoofed sender got delivered to an inbox here, and ended up somewhere I did not expect. On three of my Cloudrons, counting the Authentication-Results of everything delivered in the last 30 days, spf=temperror comes back on 14%, 21% and 31% of the messages that got an SPF verdict at all. For comparison, fail and softfail together never reach three messages per server. So temperror is by far the most common non-pass outcome, not a rare hiccup.
It is not the senders. The temperror messages are spread over 31 to 34 different sending domains per server, including icloud.com, overheid.nl, apple.com, github.com and proton.me. Those are not domains with broken SPF.
It is not a broken resolver either, at least not when you test it the obvious way. From inside the mail container, thirty lookups in a row all succeed in 23 to 40 ms, and the whole include chain resolves fine. It only falls apart when queries for different names run at the same time, which is exactly what evaluating an SPF record does:
# serial, and 30 parallel queries for the same name: fine docker exec mail bash -c 'for i in $(seq 1 30); do dig +time=2 +tries=1 +short TXT kvk.nl >/dev/null 2>&1 && echo ok || echo fail; done' | sort | uniq -c # 60 parallel queries across six different names docker exec mail bash -c 'for d in kvk.nl icloud.com overheid.nl apple.com github.com amazon.nl; do for i in $(seq 1 10); do (dig +time=2 +tries=1 +short TXT $d >/dev/null 2>&1 && echo ok || echo fail) & done; done; wait' | sort | uniq -cOn both servers the last one returns 20 ok and 40 fail. resolv.conf in the container points at 127.0.0.11, Docker's embedded DNS.
Fair warning about that test: I used +tries=1 with a 2 second timeout, so no retries. With retries the loss is smaller. The 14 to 31 percent measured on real delivered mail is the part that matters, and that is independent of how I tested.
What makes this more than a cosmetic issue is that temperror carries no penalty, and rightly so, since it means "could not be checked" rather than "failed". The effect is that SPF and DMARC are quietly not enforced on a large slice of mail, including mail from senders who publish -all and p=quarantine and do everything right. That is how a spoof of such a domain reached an inbox here at score 2.3. The same resolver is also used for the DNSBL, URIBL, DKIM and rDNS lookups, and a dropped query there just means a rule silently does not fire.
Would it be possible to give the mail container a real resolver instead of the embedded one, or is there a reason it has to be 127.0.0.11?
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login