dnscheck: query recursive resolvers directly, not the system one

The PTR check reported a correctly published record as wrong. The lookups
went through the container's resolver (127.0.0.11) which forwards to the
host's systemd-resolved, and systemd-resolved synthesises the reverse
lookup of the machine's own addresses from the local hostname rather than
asking public DNS. On the production host that meant

    81.30.105.2 -> magenta-pink-heliotrope16786 (does not match)

while public DNS has had 81.30.105.2 -> selfpost.mixfed.ru all along.

These checks exist to report what a receiving mail server sees, so they
now dial recursive resolvers themselves, defaulting to 1.1.1.1, 8.8.8.8
and 9.9.9.9 and overridable with SELFPOST_DNS_RESOLVERS. The e2e stand
sets it to its CoreDNS, which the `dns:` directive alone no longer covers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 21:53:24 +03:00
parent 12a11f185c
commit 0ca5cba453
10 changed files with 259 additions and 5 deletions
+5
View File
@@ -23,6 +23,7 @@ import (
"codeberg.org/mix/selfpost/internal/backup"
"codeberg.org/mix/selfpost/internal/buildinfo"
"codeberg.org/mix/selfpost/internal/dnscheck"
"codeberg.org/mix/selfpost/internal/logtail"
"codeberg.org/mix/selfpost/internal/store"
)
@@ -61,6 +62,7 @@ type config struct {
submissionEnabled bool
trustedProxies []*net.IPNet
sessionIdleDays int
dnsResolvers []string
// Read-only inputs to the panel's status page: the certificate Postfix
// serves and the two milter sockets it connects to. The defaults mirror
@@ -107,6 +109,9 @@ func loadConfig() config {
// Sliding session idle timeout (spec 7.6.6, plan B.1). Non-positive/invalid
// falls back to the 7-day default inside internal/web.
sessionIdleDays: envInt("PANEL_SESSION_IDLE_DAYS", 7),
// Recursive resolvers the deliverability checks query directly. Empty
// means dnscheck's public defaults; a closed network names its own here.
dnsResolvers: dnscheck.ParseResolvers(os.Getenv("SELFPOST_DNS_RESOLVERS")),
tlsCertFile: envDefault("TLS_CERT_FILE", "/etc/postfix/tls/fullchain.pem"),
opendkimSocket: envDefault("OPENDKIM_SOCKET", "/run/opendkim/opendkim.sock"),