這件事耗時調試比預期長
設置
在基於 systemd 的 Linux 電腦上運行 Caddy 作為反向代理。憑證續期透過 ACME。日誌中一切看起來都正常。然後有一天憑證過期了,兩天沒人注意到
原因
systemd-resolved 有一種行為,就是根據上游解析器的情況,對特定的 DNS 查詢返回 SERVFAIL。這並不一致。有些區域解析正常,有些則安靜地失敗。Caddy 的 ACME 客戶端發送挑戰請求,systemd-resolved 報告失敗,然後更新就... 沒有發生.
這令人煩躁的是,systemd-resolve --status 顯示沒有任何錯誤。dig 可能會對 8.8.8.8 正常運作。這個 stub resolver 才是欺騙你的應用程式,而且它並沒有記錄任何有用的資訊。
解決方法
三種處理方式:
1. 繞過 stub resolver
將 Caddy (或 Go 的 net stack 通常) 直接指向公共 resolver。在你的 Caddyfile 中:
{
servers :443 {
dns resolver 1.1.1.1
}
}
或將GODEBUG=netdns=go設置為強制使用Go解析器,而不是信任系統解析器配置.
2. 重新啟動systemd-resolved
systemctl restart systemd-resolved會清除它積累的所有錯誤狀態。這是一個暫時的解決方案 — 你會再次遇到這個問題.
更永久的解決方案是檢查/etc/resolv.conf,並確保你沒有依賴 stub 解析器來處理所有事情.
3. 使用DNS-over-HTTPS
如果你想要保持解析但讓它更穩固,請將其配置為使用 DoH 上游而不是純 UDP。無法解決 SERVFAIL 的情況,但可以避免一類 MITM 問題.
值得知道的症狀
具體的症狀:Caddy 記錄說更新失敗但沒有給出明顯的原因。caddy list 顯示證書即將過期。其他一切正常。瀏覽器會緩存證書過期警告,所以用戶停止抱怨——然後在星期一早上變成你的問題了。
結論
如果你在 systemd-resolved 上運行 Caddy,而你的證書意外過期,在檢查其他任何事物之前先檢查虛擬解析器。這種失敗是因為「DNS 正常工作」而隱藏在明顯之處。
不是贊助商。僅僅是浪費了一個下午的東西。












