NXDOMAIN:_acme-challenge記錄與權(quán)威DNS排查)
申請(qǐng)通配符或多域名證書時(shí)ACME DNS-01常見(jiàn)的第一句報(bào)錯(cuò)就是NXDOMAIN。它不是“TXT值不對(duì)”的同義詞而是查詢鏈路里連這個(gè)名字都沒(méi)有找到。先把重試按鈕放一邊查錯(cuò)名稱重試只是在給DNS服務(wù)器增加心理負(fù)擔(dān)。本文把驗(yàn)證域名、CNAME委托、權(quán)威NS、TXT傳播和DNSSEC拆開(kāi)定位到哪一層再修哪一層。一、NXDOMAIN到底說(shuō)明了什么DNS-01要求客戶端把客戶端根據(jù)token與賬戶密鑰派生出的驗(yàn)證值放在_acme-challenge.待驗(yàn)證域名的TXT記錄中ACME服務(wù)器再查詢?cè)撁Q并比對(duì)值。Let’s Encrypt官方文檔明確了這個(gè)名稱和TXT驗(yàn)證方式RFC 8555也把dns-01定義為由ACME服務(wù)器查詢DNS記錄完成驗(yàn)證。NXDOMAIN的重點(diǎn)是“名稱不存在”和NOERROR但沒(méi)有TXT、SERVFAIL、超時(shí)不是一回事。不同解析器可能緩存負(fù)結(jié)果所以改完記錄后不能只看本機(jī)一次查詢。二、先確認(rèn)ACME真正查詢的名稱最容易犯的錯(cuò)是把待簽發(fā)域名直接加TXT或者通配符寫成帶星號(hào)的查詢名。驗(yàn)證*.example.com時(shí)常規(guī)DNS-01查詢?nèi)試@_acme-challenge.example.com不是_acme-challenge.*.example.com。實(shí)際名稱以ACME客戶端日志和訂單授權(quán)對(duì)象為準(zhǔn)不要憑記憶拼接。DOMAINexample.com NAME_acme-challenge.${DOMAIN} printf query%s\n $NAME dig noall answer $NAME TXT dig noall authority $NAME TXT第一條看答案第二條看權(quán)威區(qū)是否返回SOA。若查詢名寫錯(cuò)后面的CNAME和TXT檢查都沒(méi)有意義。生產(chǎn)腳本應(yīng)把最終規(guī)范化FQDN寫入日志避免把根域、子域和通配符混成一鍋。三、區(qū)分NOERROR空答案與NXDOMAIN兩者在排障上完全不同NXDOMAIN通常表示權(quán)威服務(wù)器認(rèn)為該名字不存在NOERROR/NODATA表示名字存在但沒(méi)有所請(qǐng)求類型的記錄。若父域存在而子域不存在權(quán)威響應(yīng)里的SOA通常能幫助判斷否定緩存邊界。dig noall comments authority _acme-challenge.example.com TXT dig trace _acme-challenge.example.com TXT # 只把實(shí)際返回的狀態(tài)寫入診斷日志不用grep到空輸出就判定成功 dig noall answer _acme-challenge.example.com TXT不要只執(zhí)行dig TXT后看“沒(méi)有輸出”。保存 status、ANSWER、AUTHORITY 和 SERVER才能區(qū)分沒(méi)有記錄、被權(quán)威拒答和本地遞歸緩存異常。trace適合定位委派鏈路不代表ACME服務(wù)器一定使用同一個(gè)遞歸解析器。四、沿權(quán)威NS一路查別被本地緩存帶偏先查域名的NS再直接詢問(wèn)權(quán)威服務(wù)器。權(quán)威服務(wù)器沒(méi)有記錄而公共遞歸仍有舊TXT說(shuō)明緩存尚未過(guò)期權(quán)威已有記錄而本地仍NXDOMAIN則優(yōu)先檢查負(fù)緩存、查詢線路和DNSSEC。ZONEexample.com dig short NS $ZONE for ns in $(dig short NS $ZONE); do printf \nserver%s\n $ns dig noall comments answer authority \ $ns _acme-challenge.$ZONE TXT done本例驗(yàn)證區(qū)域根域查子域時(shí)單獨(dú)指定NAME不能把查詢名改成區(qū)域根域。ZONE應(yīng)為實(shí)際權(quán)威區(qū)域子區(qū)委派需用trace確認(rèn)。若DNS服務(wù)商控制臺(tái)顯示記錄但權(quán)威NS回答沒(méi)有它常見(jiàn)原因是改錯(cuò)了賬戶、區(qū)域或記錄名若權(quán)威回答正確再看遞歸緩存和傳播不要繼續(xù)改記錄。五、CNAME委托時(shí)查目標(biāo)不要同時(shí)塞CNAME和TXT如果把_acme-challenge.example.comCNAME到專用驗(yàn)證域TXT通常應(yīng)放在CNAME目標(biāo)上。DNS名稱不能同時(shí)把同名CNAME和其他數(shù)據(jù)記錄當(dāng)成普通并列項(xiàng)使用委托目標(biāo)也必須再追到它自己的權(quán)威NS。NAME_acme-challenge.example.com dig noall answer $NAME CNAME TARGET$(dig short $NAME CNAME | sed s/\.$//) if [ -n $TARGET ]; then dig noall answer $TARGET TXT dig noall authority $TARGET TXT fi這里有個(gè)很隱蔽的坑CNAME目標(biāo)末尾的點(diǎn)表示完整域名API填值時(shí)有的服務(wù)商要求相對(duì)名有的要求FQDN。最終以權(quán)威查詢結(jié)果為準(zhǔn)。若歷史TXT殘留先確認(rèn)是否屬于仍在進(jìn)行的并發(fā)驗(yàn)證再按服務(wù)商語(yǔ)義刪除不能用“清空全部TXT”這種粗暴方案。六、DNSSEC、SERVFAIL和傳播延遲怎么分層NXDOMAIN修正后變成SERVFAIL方向可能已經(jīng)從記錄名轉(zhuǎn)到DNSSEC、簽名過(guò)期或委派不一致。對(duì)比普通解析器、權(quán)威NS和帶DNSSEC校驗(yàn)的結(jié)果不要把SERVFAIL當(dāng)作TXT值錯(cuò)誤。響應(yīng)現(xiàn)象通常含義先做什么NXDOMAIN權(quán)威認(rèn)為名稱不存在查驗(yàn)證名稱、區(qū)域和委派NOERROR無(wú)TXT名稱存在但沒(méi)有TXT查記錄類型、目標(biāo)和生效區(qū)SERVFAIL解析鏈或DNSSEC失敗查權(quán)威狀態(tài)、簽名和委派NOERROR有舊TXT能查到但值不匹配保留并發(fā)值核對(duì)token后重試DNS傳播不是一個(gè)固定秒數(shù)。TTL影響緩存但負(fù)緩存還受SOA中的否定緩存參數(shù)影響權(quán)威服務(wù)器、遞歸解析器和CA驗(yàn)證器看到的時(shí)間可能不同。修改后等待并重復(fù)查詢比連續(xù)創(chuàng)建新訂單更穩(wěn)妥。七、用三種方案做中立對(duì)照純命令行可以直接調(diào)用DNS Provider APIacme.sh等開(kāi)源客戶端也能通過(guò)DNS API自動(dòng)寫入TXT平臺(tái)化方案則通常把訂單、權(quán)限、重試和多目標(biāo)部署統(tǒng)一管理。無(wú)論選哪種核心驗(yàn)收都一樣寫入的是正確驗(yàn)證名稱權(quán)威NS能查到正確TXT驗(yàn)證完成后按策略清理舊值。本文只作技術(shù)邊界對(duì)照不把某個(gè)方案寫成唯一答案。參考Let’s Encrypt DNS-01文檔、acme.sh開(kāi)源倉(cāng)庫(kù) 與 CertbotX。八、續(xù)期前驗(yàn)收清單從ACME日志取出準(zhǔn)確授權(quán)域名確認(rèn)沒(méi)有把星號(hào)寫進(jìn)查詢名。遞歸查詢與至少一臺(tái)權(quán)威NS分別讀取TXT并記錄status、ANSWER和AUTHORITY。存在CNAME時(shí)只沿目標(biāo)查TXT確認(rèn)目標(biāo)區(qū)域和末尾點(diǎn)語(yǔ)義。把NXDOMAIN、NOERROR空答案、SERVFAIL和舊TXT分開(kāi)處理。確認(rèn)驗(yàn)證完成后再清理對(duì)應(yīng)TXT不刪除并發(fā)訂單仍需要的值。最終用ACME staging或受控測(cè)試訂單復(fù)驗(yàn)再接入自動(dòng)續(xù)期和告警。事實(shí)依據(jù)RFC 8555 第8.4節(jié)、Let’s Encrypt Challenge Types文檔。線上證書是否真正更新還要另行讀取部署節(jié)點(diǎn)的證書指紋和有效期DNS查詢成功不等于Nginx已經(jīng)加載新證書。