KAKESU~/@dotbind-kondo/cloudflare-origin-ssl-expired-zenlogic

Cloudflare 経由のサイトで、オリジン(Zenlogic)の SSL 証明書切れにより閲覧できなくなった件の対応

trail

観察エッジは https で 200。オリジンの証明書だけ前日に期限切れ
観察Zenlogic の自動更新の確認通信が、Cloudflare のルールに止められていた
却下acme-challenge だけ WAF やリダイレクトの対象外にする案。Zenlogic が DNS の向き先も見ていれば通らず、90日ごとに不安が残る
却下更新のたびにグレー雲へ切り替える案。毎回手作業になり、オリジンの IP も外から見える
決定Cloudflare Origin CA 証明書(15年)を Zenlogic に持ち込む
観察既存の Origin 証明書は秘密鍵が残っておらず、PC とセッション履歴を探しても見つからない
決定新しく作り直す。古いほうは使用先が分からないので失効させない
観察apex だけ切り替わり、www は古いまま。Zenlogic はホストごとに設定が別
観察SSL/TLS モードの自動判定が「オフ」に落ちていた
決定フル(厳格)に固定。異常を 526 として表に出す
却下Health Checks で監視する案。Free プランでは使えない(Pro 以上)
決定Cron の Worker で30分ごとに監視し、状態が変わったときだけ Slack に通知

背景

クライアントのサイト(旧 WordPress、オリジンは Zenlogic、手前に Cloudflare のプロキシ)で、サイトの一部が見られなくなった。オリジンの SSL 証明書の期限が切れていたことが原因だった。Cloudflare からは何の通知もなく、気づくのが遅れた。

※ クライアント名・ドメイン・オリジンの IP・アカウント ID・秘密鍵・Webhook URL は省略した。

調査

  • 閲覧者から Cloudflare まで(エッジ)の証明書は Google Trust Services で有効。http→https の 301 も正常。
  • オリジン(Zenlogic)の証明書は DigiCert(Encryption Everywhere)で、前日に期限切れになっていた。
  • 自動更新できなかった原因:Zenlogic の無料 SSL は /.well-known/acme-challenge/ へのアクセスで更新を判定する。DNS が Cloudflare のプロキシ経由なので、その通信が Cloudflare のルールに止められていた。
  • Cloudflare の SSL/TLS モードは「自動」になっていて、実際には 「オフ(保護なし)」に落ちていた。オリジンの証明書が切れていたため、自動判定で格下げされたと思われる。つまり、Cloudflare からオリジンまでは http のまま流れていた。
  • Cloudflare には2041年期限の Origin 証明書がすでにあったが、秘密鍵がどこにも残っていなかった。PC 内とエージェントのセッション履歴も探したが見つからなかった。秘密鍵は作成したときに一度しか表示されず、あとからダウンロードできるのは証明書(PEM)だけ。
  • Zenlogic の SSL の設定はホストごとに別。最初は apex(example.jp)にだけ登録していて、www は古い証明書のままだった。SNI を www と apex の両方に変えて openssl s_client で確かめて気づいた。
  • ゾーンは Cloudflare の Free プラン(API で確認)。Health Checks(Pro 以上)も Origin Error Rate Alert(Enterprise)も使えない。

判断

  • Cloudflare Origin CA 証明書を新しく作成した(RSA、*.domain と apex、15年)。Zenlogic の「他社で取得した証明書」の登録画面で、www と apex の両方に登録した。これで更新作業はなくなる。
  • 古い Origin 証明書は、使われている場所が分からないので失効させずに残した。
  • SSL/TLS モードは「自動」ではなく フル(厳格)に固定した。自動だと異常時に気づかないまま「オフ」に格下げされてしまう。固定しておけば、異常があれば 526 エラーとして表に出る。
  • Free プランで使えるアラート(HTTP DDoS Attack・Universal SSL・Security Insights・Abuse report)をメール通知で設定した。管理画面での場所は Observability → アラート。
  • オリジンの死活監視は Cron Trigger の Worker で自作した。
  • 30分ごとに、トップページ(本文の文字列も確認)・下層ページ・CSS の3か所を確認する。
  • 失敗した URL は3秒後にもう一度確認してから異常と判断する。
  • 状態を KV に保存し、正常と異常が切り替わったときだけ Slack に投稿する。
  • キャッシュを避けるため、毎回クエリを付けて取得する。公開 URL は付けていない。
  • 負荷は1日48回×3 URL 程度で、サイトにも Workers の無料枠にも影響はない。
  • 担当者には、原因(Cloudflare のセキュリティ設定が証明書の更新確認を止めていた)と対応を短くまとめて報告した。

Next Action

  • Slack の Webhook URL を Worker のシークレットに登録し、最初の「監視開始」の通知が届くか確かめる。
  • Worker からのアクセスが WAF や Bot 対策に止められないか、本番の最初の実行ログで確かめる。
  • 新しい Origin 証明書の秘密鍵を、チームで共有できる安全な場所に保管する。手元の一時ファイルは削除する。
  • 証明書を作るときは、秘密鍵の保管場所を記録に残すことを手順に入れる(今回は鍵が見つからず、作り直すことになった)。