Wordpress

SSL 憑證續期為什麼會悄悄失敗?連到期提醒信都停了

多數人一裝上 Certbot、設定好自動續期,就把 SSL 憑證這件事徹底歸類成「不用再管」的項目。這個想法一度是對的,但現在已經行不通。續期背後那套自動化排程,只要中間有一個環節被悄悄擋住,就會不聲不響地持續失敗,直到某天有訪客打開網站,瀏覽器跳出警告,才第一次讓人知道出事。

SSL 憑證續期指的是網站在憑證到期前,重新向憑證授權機構申請、換發一張新憑證的過程;免費憑證機構 Let’s Encrypt 的憑證效期只有 90 天,理論上全靠自動化排程處理,人完全不用碰。真正的問題不在自動化本身,而在於這套自動化一旦遇到問題,過去還有一道最後防線,那就是 Let’s Encrypt 會在憑證快到期時,寄一封提醒信到申請當下登記的信箱。這封信在 2025 年已經停止寄送,代表現在如果續期進行不下去,不會再有任何外部訊號提醒你。

自動續期機制與它預設暢通的驗證管道

Let’s Encrypt 憑證的效期只有 90 天,裝好 Certbot 之後,實際負責「自動續期」的是作業系統裡的排程工具,systemd timer 或 cron,由它定期喚醒 Certbot 去檢查目前所有已安裝的憑證還剩多少天效期。

Certbot 官方文件說明,自 Certbot 4.0.0 版起,只要憑證剩餘效期少於整體效期的 1/3 就會被視為可以續期;效期在 10 天以下的憑證,門檻則放寬到剩餘效期的 1/2。4.0 版之前的規則比較單純,固定是剩餘 30 天以下才續。也因為 certbot renew 設計成只在真的接近到期時才動作,官方才敢建議把它排進每天或每週都跑一次的排程,不會有重複核發的副作用。

確認排程週期到了、決定要續期之後,接下來是憑證授權機構要確認「這個網域真的是你在管理」,最常見的做法是 HTTP-01 驗證,整個流程是先由 Let’s Encrypt 發一個權杖給 Certbot,Certbot 把這個權杖連同帳戶金鑰的指紋寫成一個檔案,放進網站根目錄底下的 /.well-known/acme-challenge/ 路徑,接著 Let’s Encrypt 的伺服器對外發出一個 HTTP 請求,讀取這個檔案內容,比對得上就代表驗證通過。Let’s Encrypt 官方對「不確定該選哪種驗證方式」給的建議是「採用用戶端預設設定或 HTTP-01」,換句話說,多數自動化流程實際上跑的就是這套機制。

整套自動化聽起來滴水不漏,問題出在一個沒被明講的前提,那就是 HTTP-01 驗證要成立,Let’s Encrypt 的伺服器必須能從外部順利連進網站、讀到那個驗證檔案。這條路一旦被擋,certbot renew 不會跳出警訊,也不會寄信通知,它只會在下一個排程週期照樣嘗試、照樣失敗,行為跟「一切正常、還沒到續期時間」看起來一模一樣。這也是為什麼多數人直到瀏覽器對訪客顯示警告的那一刻,才第一次意識到問題已經存在了一段時間。

自動續期只要在寫入驗證檔或對外讀取的環節被安全外掛、防火牆或 WAF 攔截,certbot renew 就會靜默失敗、不跳警訊也不寄信。
HTTP-01 驗證的任一環節被擋,續期就會在背景不聲不響地失敗,外觀和「還沒到續期時間」看起來一模一樣。

官方到期提醒信,已在 2025 年停止寄送

前面那個沒被明講的前提,其實有很長一段時間被一道防線遮住,就算續期真的停在這一步,Let’s Encrypt 過去還會在憑證快到期時,寄一封提醒信到申請當下登記的電子郵件信箱,等於留給網站維護者最後一次補救的機會。

這道防線在 2025 年 6 月 4 日正式關閉。Let’s Encrypt 官方公告列出了幾個理由:過去十年間,愈來愈多使用者已經建立起可靠的自動化續期機制,通知信的必要性愈來愈低;維運這項服務每年要花上數萬美元;系統本身也因為這項服務多了一層複雜度,多了一個出錯的機會;更根本的是,長期保留數百萬筆跟憑證核發紀錄綁在一起的電子郵件地址,跟組織重視隱私的立場本來就相牴觸。公告發布後,Let’s Encrypt 已經把儲存在核發紀錄裡的這些電子郵件地址刪除,原本訂閱的一般電子報則不受影響。

這代表往後如果續期在背景找不到方向,不會再有任何被動提醒,不是信件晚到,而是根本不會有這封信。監控到期日這件事,從「憑證授權機構會幫你顧最後一道防線」,徹底變成「完全要靠網站維護者自己想辦法」。

Let’s Encrypt 官方在公告裡也給出替代做法,建議改訂閱第三方監控服務,並具體點名 Red Sift Certificates Lite(前身是 Hardenize)可以免費監控最多 250 張憑證的到期狀態。這代表監控責任轉移到獨立於憑證授權機構之外的工具,是官方自己認可的合理做法,而不是留給使用者自己想辦法的空白地帶。

讓驗證請求受阻的四種常見情境

監控能提前示警,但真正要解決問題,還是得先弄懂驗證為什麼會失敗。HTTP-01 驗證要暢通,牽涉到伺服器設定、資安規則、轉址邏輯好幾個環節,任何一個環節被調整過,都可能連帶擋住授權機構的驗證請求。以下四種情境是實際上最常見的成因,依常見程度排列。這四種情境有一個共通點,當初做這個設定調整的目的通常跟憑證完全無關,多半是為了加強資安防護、優化 SEO 轉址,或是提升網站效能,設定當下不會特別想到會波及 .well-known/acme-challenge 這條路徑。

讓 HTTP-01 驗證受阻的四種常見情境:安全外掛封鎖隱藏目錄、防火牆或 WAF 誤判流量、搬家改轉址後路徑跑掉、排程本身停擺。
這四種設定當初多半是為了資安、SEO 轉址或效能,沒想到會一起波及憑證的驗證路徑。

安全外掛與伺服器規則對隱藏目錄的整批封鎖

許多資安外掛與伺服器層級的防護規則,會把「以英文句點開頭的隱藏目錄」整批視為預設該擋的可疑路徑,.well-known 正好符合這個特徵。有些規則更進一步,要求存取這類目錄前先通過額外驗證,結果連授權機構的驗證請求也一起被擋在外面。這類規則多半是在啟用外掛的「加強防護」選項,或是套用某套資安基準設定時被打開的,設定當下不會有人特別去想到它會影響憑證續期。

Certbot 官方文件明確提到這個坑,如果伺服器設定把 /.well-known 目錄做了特殊處理,可能需要額外調整,確保 /.well-known/acme-challenge 底下的檔案能被伺服器正常提供。連官方都把這種情況列為需要使用者自行排查的已知情境,而不是會自動處理好的邊角案例,代表它在實務上發生的頻率不低。

防火牆或 WAF 把驗證流量誤判成異常請求

防火牆規則收緊、雲端服務商的安全群組設定變動,或是 WAF 規則更新之後,授權機構驗證伺服器發出的請求,有可能被判定成機器人流量或異常請求而直接遭到攔截,導致驗證逾時失敗。透過 CDN 或反向代理服務轉發流量的網站,如果代理層沒有正確把 .well-known/acme-challenge 的請求轉發到源站,也會造成一樣的結果。

Certbot 官方文件在說明 webroot 挑戰的運作方式時,附了授權機構驗證伺服器實際發出請求的紀錄範例,使用者代理字串是 Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)。這串文字可以直接拿去比對防火牆或 WAF 的日誌,確認是不是這個特徵被某條規則擋下,不必憑印象猜測。

搬家或改了轉址規則後,驗證路徑跟著跑掉

全站強制 HTTP 轉 HTTPS、加了新的 URL 轉址規則,如果沒有把 .well-known/acme-challenge 排除在轉址範圍之外,驗證請求就會被導去別的網址,或收到不是原本預期的回應內容,驗證自然失敗。換主機、搬家之後,如果網站根目錄(webroot)的實際路徑跟 Certbot 原本設定的路徑對不上,也會出現「驗證檔案明明存在,卻讀不到」的同一種結果。

Certbot 官方文件說明 webroot 挑戰的運作方式時指出,驗證檔案會被寫進 ${webroot-path}/.well-known/acme-challenge 這個路徑,授權機構隨後對外發出 HTTP 請求讀取。一旦這個 webroot-path 跟網頁伺服器實際服務靜態檔案的路徑對不上,驗證就會失敗,而這正是搬家或改動轉址規則後最容易發生的落差。

外部觀察不出排程停擺和排程被擋的差別

還有一種情況是排程本身根本沒有在跑。系統套件更新、環境搬遷,或是代管主機商後端服務出狀況,都可能讓原本設定好的 systemd timer 或 cron 被停用,而且沒有人會發現。因為續期在「還沒到門檻」的時候本來就不會有任何動靜,這種「排程真的停了」的狀態,跟前面三種「排程有跑但被擋」的狀態,從外部觀察起來是同一種沉默,得靠實際排查才分得出來。

Certbot 官方文件提供 systemctl list-timers 這個指令,可以列出系統上所有作用中的 systemd 計時器,用來確認負責續期的排程本身是不是還在運作;搭配前一節提到的續期觸發門檻,就能判斷眼前這個「沒有動靜」,是因為還沒到門檻,還是已經到門檻卻持續失敗。

從「網站顯示不安全」回推到真正原因的排查順序

要抓出問題出在哪裡,不需要打開設定憑感覺亂猜,順著三個步驟由粗到細往下查就好,先確定問題發生多久了,再用官方工具重現失敗當下真正的錯誤訊息,最後才回頭對照上一節的四種情境逐一排除。順序很重要,一開始就栽進某個猜測方向,反而容易繞遠路。

先確認到期時間與最近一次續期紀錄

第一步是先把事實釐清,而不是急著動手修。用瀏覽器點擊網址列的鎖頭圖示,或用命令列工具查詢,就能確認憑證實際的到期日;接著要去查伺服器上 Certbot 記錄的續期日誌,確認這次的失敗是「剛好碰上這一次」,還是「已經連續失敗好幾個週期」。

這一步的結果決定接下來該往哪個方向查。如果日誌顯示已經連續失敗超過一個月,代表問題不是網路一時的抖動,而是某個設定持續在擋;如果只有這一次失敗,則比較可能是暫時性的異常。Certbot 官方文件說明,certbot certificates 指令會列出所有已知憑證的名稱、涵蓋網域、到期日與憑證檔案路徑,官方文件也提到 Certbot 預設會把狀態日誌存放在 /var/log/letsencrypt,裡面留有續期歷程,可以用來回推問題從什麼時候開始。

用官方模擬指令重現失敗的真正訊息

確認問題已經持續一段時間之後,下一步是用 certbot renew --dry-run 完整跑一次續期流程,包含所有設定好的掛勾腳本,但不會真的把憑證寫入正式環境。因為它連接的是測試環境,不會受到正式環境的請求頻率限制,可以放心反覆測試,不用擔心把額度用完。

這一步的價值在於它會直接印出真正的失敗原因,是連線逾時、驗證檔案讀不到回傳 404,還是驗證伺服器有收到內容但比對失敗,比自己憑感覺猜測上一節四種情境哪一種命中要準確得多。Certbot 官方文件也提醒,如果確定要手動反覆重試正式續期,應該避免濫用 --force-renewal,因為每一次成功核發都會計入憑證授權機構的請求頻率限制,很快就會撞到上限,這也是為什麼官方建議測試一律用 --dry-run

直接測試驗證路徑的實際回應狀態

最後一步是繞過猜測,直接還原授權機構當下做的事,在瀏覽器或用命令列工具,對自己網站的 /.well-known/acme-challenge/ 路徑發出請求,看看能不能拿到正常回應。

如果連自己手動測試都讀不到內容,問題幾乎可以鎖定在伺服器設定、安全外掛,或防火牆這一端,而不是憑證授權機構那一端;如果手動測試一切正常,正式驗證卻仍然失敗,就要回頭懷疑是不是有規則專門針對授權機構的請求特徵做了區別對待,例如前面提到的那組使用者代理字串。Certbot 官方文件本身就把「手動確認 .well-known/acme-challenge 底下的檔案能否被伺服器正常提供」列為排查前提,這一步是官方認可的做法,不是土法煉鋼。

自己能修的範圍,與該找主機商的分界

前面列的排查步驟,誰能動手修,取決於有沒有實際管理伺服器設定與 ACME 用戶端的權限,不必在自己完全碰不到的層級反覆嘗試、白白浪費時間。

自架伺服器,問題通常出在自己動過的設定

如果是自己安裝 Nginx 或 Apache、自己跑 Certbot 的情況,前面列的四種常見情境幾乎都指向同一個方向,自己最近改過什麼。可能是裝了新的安全外掛、調整了防火牆規則,或是加了新的轉址規則。修法很直接,回頭比對最近的變更紀錄,通常能對得上出問題的時間點。

如果網站的架構本身讓對外開放 80 埠變得困難,例如伺服器沒有公開對外的路由,也可以考慮改用 DNS-01 驗證,把驗證方式從「對外接受連線」換成「在 DNS 裡放一筆 TXT 紀錄」,繞開連線層面的限制。Let’s Encrypt 官方說明,DNS-01 驗證要求在網域名稱底下、以 _acme-challenge 為前綴的 TXT 紀錄放入特定值,憑證授權機構隨後查詢 DNS 系統驗證這筆紀錄。官方也列出這個做法的優點,包括可以核發萬用字元憑證,也能驗證沒有公開曝露在網路上的網域。

不過這不是萬能解法,而是用一種限制換另一種限制。官方文件明白提醒,把 DNS 服務商的 API 憑證留在網頁伺服器上有風險,一旦伺服器被入侵,攻擊者能動用的權限範圍會跟著擴大;而且並不是所有 DNS 服務商都提供可以自動化操作的 API,換驗證方式之前,得先確認自己用的 DNS 服務商支不支援。

代管主機一鍵簽發時,問題可能出在主機商那端

如果用的是代管主機內建的一鍵 SSL 服務,不是自己手動跑 ACME 用戶端,能自己排查的範圍相對有限,通常只能確認自己有沒有裝會擋路徑的安全外掛,有沒有動過轉址規則。

排除這些之後問題仍然存在,代表可能是主機商後端的憑證簽發服務本身出狀況,或是主機層級的防火牆規則有變動。這種情況下,正確的下一步是直接聯絡主機商客服,說明「驗證持續失敗、已經排除外掛與轉址規則」這個具體結論,而不是在自己能碰到的範圍裡反覆瞎猜。

把到期日放進監控,補回官方拿掉的安全網

官方到期提醒信已經停止,監控到期日這件事,現在完全落回網站維護者自己身上。以下三個做法互相補強,不是三選一,分別對應「被動提醒」「主動驗證」「預先防堵」三個層次。

續期在背景失敗到憑證到期、瀏覽器跳警告之間有一段沒有警訊的空窗,可用第三方監控、改設定後模擬續期、把驗證路徑列進允許清單三道防線提前補上。
官方到期提醒信已於 2025 年停止,靠第三方監控、改動後模擬續期與允許清單,就能在空窗期內提前把問題攔下。

訂閱第三方到期監控,補回官方拿掉的通知

既然官方通知信已經停止,最直接的做法是訂閱一個獨立於憑證授權機構之外的監控服務,讓它定期檢查憑證到期日,在到期前提早用電子郵件或其他管道主動告警。這類服務通常設定一次就能長期運作,把「有沒有人記得去查」這件事,從仰賴人力變成自動化流程。

Let’s Encrypt 官方在公告終止通知信服務的同時,已經具體點名 Red Sift Certificates Lite 可以免費監控最多 250 張憑證,這代表監控責任轉移到第三方工具,是官方自己認可的替代路徑,而不是留給使用者自己想辦法的空白地帶。

改動安全規則或搬家後隨手做一次模擬續期

比起等 90 天週期自然發生才知道結果,更務實的做法是把「安裝新的安全外掛」「調整防火牆規則」「改動 URL 轉址規則」「搬家換主機」這幾個動作,跟「立刻跑一次模擬續期」綁在一起,變成例行程序的一部分。

即使某個改動不小心波及了驗證路徑,也能在問題還沒真的累積到憑證過期之前就先被抓到,不必等到瀏覽器對訪客跳出警告才發現。--dry-run 本來就是設計給反覆測試、不受頻率限制的情境使用,把它從「出事後才用來排查」提前挪到「改動設定後主動驗證」,是同一個官方工具的不同用法,不需要另外導入第三方系統。

把驗證路徑明確列進安全規則的允許清單

比起關掉安全防護來換取續期順利,更好的做法是明確把 .well-known/acme-challenge 這個路徑,寫進安全外掛、防火牆、WAF 的允許清單,讓它不受一般規則管制、永遠允許外部讀取。

這樣一來,下一次資安規則更新、外掛升級,或是套用新的資安基準設定時,才不會又把這條路徑意外納入封鎖範圍,重演同一個問題。Certbot 官方文件本身就把「確保 .well-known/acme-challenge 底下的檔案能被伺服器正常提供」列為需要使用者主動設定、而非預設會自動處理好的項目,把這個路徑寫進允許清單,是官方文件本來就建議的做法,不是額外的偏方。

自動續期本來就不是「裝完就永遠不用管」的功能,它只是把重複的申請流程自動化,驗證路徑暢不暢通、排程有沒有真的在跑,還是得靠人自己留意。過去有官方通知信兜底,即使一時沒注意到也還有補救機會;這道防線拿掉之後,監控到期日、養成改動設定後隨手驗證的習慣,就成了每個網站維護者自己該扛起來的基本功。把這幾件事排進日常維運節奏裡,SSL 憑證續期失敗這種本來就不該發生的意外,自然也就少了發生的空間。

常見問答

本區問答由 AI 依文章內容自動整理,僅供快速參考,正式內容仍以全文為準。

Let's Encrypt 的到期提醒信何時停止寄送?

Let’s Encrypt 已在 2025 年 6 月 4 日正式停止寄送憑證到期提醒信,官方公告提到多數使用者已建立可靠的自動化續期機制、通知信必要性降低,加上維運成本與隱私考量,因此關閉這項服務,並已刪除核發紀錄裡保留的電子郵件地址。

HTTP-01 驗證怎麼確認網域是你在管理?

Let’s Encrypt 先發一個權杖給 Certbot,Certbot 寫成驗證檔放進 /.well-known/acme-challenge/ 路徑,接著對外發出 HTTP 請求讀取這個檔案,比對得上就代表驗證通過。

為什麼安全外掛容易擋掉 SSL 續期驗證?

許多資安外掛與伺服器規則會把以句點開頭的隱藏目錄整批視為可疑路徑而封鎖,.well-known 正好符合這個特徵,連授權機構的驗證請求也會一併被擋下;這類規則多半是在啟用外掛「加強防護」選項時被打開的,設定當下不會特別想到會波及續期。

為什麼要先用 dry-run 模擬續期?

certbot renew –dry-run 會完整跑一次續期流程並印出真正的失敗原因,例如連線逾時、驗證檔案讀不到,或內容比對失敗;因為連的是測試環境、不受正式環境的請求頻率限制,可以放心反覆測試,不用擔心把額度用完。

代管主機的 SSL 續期失敗該找誰處理?

先自行確認有沒有裝會擋路徑的安全外掛、有沒有動過轉址規則,排除這些之後問題仍然存在,就代表可能是主機商後端的憑證簽發服務或防火牆規則出狀況,這時應直接聯絡主機商客服,說明已排除外掛與轉址規則的具體結論。

資料來源
  1. Expiration Notification Service Has Ended — Let's Encrypt
  2. User Guide — Certbot Documentation — Certbot
  3. Challenge Types — Let's Encrypt