WordPress SSL 進階設定:HSTS、混合內容與 Let’s Encrypt 自動續約排查

網站從 HTTP 切換到 HTTPS 那一刻,大多數人以為工作已告結束。憑證裝好、瀏覽器顯示鎖頭、Google Search Console 也沒報錯,看起來一切正常。但 WordPress SSL 設定其實只完成了一半——HSTS 啟用時機、混合內容(Mixed Content)警告的清理,以及 Let’s Encrypt 自動續約的穩定性,這三塊才是決定「真正安全」還是「差一點安全」的分水嶺。

這篇文章的範圍鎖定這三個方向,逐一說明機制、風險,以及遇到問題時該從哪裡著手。

HSTS 啟用的時機與不可逆風險

HSTS(HTTP Strict Transport Security,HTTP 嚴格傳輸安全)是一組加在伺服器回應標頭裡的指令,告訴瀏覽器「這個網域未來只准走 HTTPS,不管使用者輸入什麼」。聽起來簡單,但它的核心風險藏在「不可逆」三個字裡。

啟用 HSTS 後,瀏覽器會把指令快取到本機,有效期間由 max-age 決定,常見設定是 31536000 秒(365 天)。在這段期間內,即使取消 HTTPS、憑證過期或主機出狀況,瀏覽器仍然拒絕以 HTTP 連入,網站對那些已快取過 HSTS 的訪客來說會直接無法存取——沒有任何繞過的辦法,除非等快取到期或使用者手動清除。

啟用 HSTS 的前提條件要全部到位才能動手。

  • 憑證穩定性確認:HTTPS 要運作至少 1 到 2 個月,確認自動續約機制正常,才適合啟用 HSTS。
  • 全站重新導向健全:HTTP → HTTPS 的 301 轉址要涵蓋所有子網域,沒有遺漏或例外路徑。
  • 子網域全部就緒:如果計畫啟用 includeSubDomains 選項,每個子網域都必須有有效的 HTTPS,否則那些子網域同樣會被鎖定。
  • preload 慎用preload 選項會把網域提交到各大瀏覽器的內建清單,從此不論快取是否到期,瀏覽器永遠強制 HTTPS。要從清單移除需要申請,且可能需要數個月才能生效。

WordPress 站台若使用 Really Simple SSL 外掛,HSTS 功能藏在「設定 > SSL」裡的進階標頭選項,預設不啟用,需要手動開啟。開啟前務必確認以上四點已全部達成。

混合內容警告的來源與處理邏輯

網站切換到 HTTPS 後出現混合內容警告,根源幾乎都一樣:頁面已走 HTTPS,但頁面裡有部分資源——圖片、JavaScript、CSS、影片嵌入——仍以 HTTP 協議被呼叫。瀏覽器把這種狀況視為安全漏洞,因為未加密的資源理論上可能在傳輸途中被竄改。

混合內容分兩類,嚴重程度不同。被動混合內容(Passive Mixed Content)指圖片、音訊、影片,瀏覽器通常會載入但顯示警告;主動混合內容(Active Mixed Content)指 JavaScript 和 CSS,因為這類資源能直接操作頁面行為,現代瀏覽器預設會直接封鎖,不是警告而是拒絕執行。

常見來源

WordPress 的混合內容問題通常集中在幾個位置。

  • 資料庫裡的硬寫 HTTP 網址:遷移到 HTTPS 時,如果只改了 WordPress 設定裡的「網站網址」,卻沒有批次替換資料庫中的 URL,文章內容、小工具、選單、外掛設定裡的舊連結仍然是 HTTP。
  • 外部嵌入資源:YouTube、Vimeo、地圖嵌入若使用舊版 http:// 嵌入碼,會成為主動或被動混合內容;第三方廣告腳本、追蹤像素、舊版內容傳遞網路(CDN)設定也是常見來源。
  • 佈景主題與外掛的硬編碼路徑:部分較舊的佈景主題或外掛在 PHP 原始碼裡寫死 http:// 開頭的資源路徑,而非使用 WordPress 的 home_url() 或相對路徑。

Really Simple SSL 的修正機制

Really Simple SSL 的核心功能之一,就是在頁面輸出時用 PHP 的輸出緩衝(Output Buffering)掃描 HTML,把 http:// 開頭的資源網址即時替換成 https://。這個做法對資料庫硬寫問題特別有效,不需要直接動資料庫就能解決大多數警告。

但這個機制有限制。它只能處理「頁面 HTML 輸出」裡的靜態網址,對於由 JavaScript 動態插入的資源、或透過 AJAX 載入的內容,即時替換無法覆蓋。遇到這類情況,需要配合瀏覽器開發者工具的「控制台」或「網路」面板,找出實際觸發的 HTTP 請求來源,再從根本修改程式碼或嵌入碼。

掃描工具方面,外掛內建的掃描功能可以列出已知的問題資源;SSL Labs 的線上檢測(ssllabs.com/ssltest)可驗證憑證設定;瀏覽器的開發者工具則是定位動態混合內容最直接的手段。

Let’s Encrypt 自動續約失敗的排查方向

Let’s Encrypt 憑證有效期 90 天,設計上依賴自動化工具(通常是 Certbot 或主機控制面板的內建機制)在到期前 30 天自動續約。大多數情況下這個流程不需要人工介入,但當它失敗時,往往會在毫無預警的情況下讓網站突然顯示憑證錯誤。

自動續約失敗有幾個常見根因,排查要從下列方向著手。

  • DNS 解析問題:Let’s Encrypt 在驗證時需要能從外部存取網域,如果 DNS 設定近期有變更(例如換主機後尚未完全生效),驗證請求可能打到舊 IP,導致失敗。確認方式是從外部網路用 dig 或線上 DNS 工具確認域名解析指向正確的伺服器。
  • HTTP-01 驗證路徑被封鎖:Certbot 預設使用 HTTP-01 驗證,需要在 http://your-domain/.well-known/acme-challenge/ 放置暫時驗證檔。若 .htaccess 有規則把所有 HTTP 請求強制轉址到 HTTPS,或防火牆、CDN 設定封鎖了這個路徑,驗證就會失敗。解決方式是在轉址規則前加例外,讓 /.well-known/acme-challenge/ 的 HTTP 流量直接通過。
  • Cron 任務未執行:VPS 或獨立主機環境下,自動續約通常靠系統排程(cron)觸發。若排程設定被刪除或執行帳號無權限,續約流程根本不會啟動。用 crontab -lsystemctl status certbot.timer 確認任務是否存在且正常執行。
  • 主機控制面板的自動續約設定:使用 cPanel、Plesk 等控制面板的站台,Let’s Encrypt 整合通常由面板自行管理。若憑證顯示無法自動續約,先進入面板的 SSL 管理介面確認設定狀態,再查面板的錯誤日誌,而非直接用 Certbot 指令操作——兩者同時管理同一憑證可能產生衝突。
  • 速率限制:Let’s Encrypt 對同一網域每週最多簽發 5 張憑證。若測試期間反覆申請,可能觸發速率限制,導致後續申請全部失敗直到限制解除。這不是系統問題,等待一週或改用 Let’s Encrypt 的 staging 環境測試是正確做法。

收到續約失敗的告警後,最快的確認方式是直接執行 certbot renew --dry-run,它會模擬完整的續約流程但不實際寫入憑證,輸出訊息通常能明確指出失敗原因。排查清楚根因後再執行正式的 certbot renew 即可。

憑證裝好只是起點。HSTS 的謹慎啟用、混合內容的徹底清理,以及自動續約的可靠運作,三者合在一起,才能確保訪客看到的始終是完整、無誤的安全連線。

相關文章
標籤: Let's Encrypt, WordPress SSL, HSTS, 混合內容, Really Simple SSL