443ポートを塞いだまま Let’s Encrypt 更新

ここ最近、ストーカーのような海外アクセスが多く、
サーバーの 443 ポートを「日本+検索ボット限定」に絞り込んでいました。

ところが、思わぬ副作用が。
Let’s Encrypt(certbot)で証明書を更新しようとしたところ、

Timeout during connect (likely firewall problem)

というエラー。
原因は 認証サーバーが海外から 443 にアクセスしてくるのに、こちらで塞いでいたため。

試行錯誤の記録

preferred-challenges = http を設定してみた
→ でも /.well-known/acme-challenge/ が https にリダイレクトされてしまうため、やはり失敗。

ログに outbound1.letsencrypt.org のアクセスを発見!
→ これで「確かに来ているのに 301 リダイレクトされてる」ことが判明。

RewriteCond で acme-challenge を例外扱い に修正

RewriteEngine On

Let’s Encrypt 用は例外

RewriteCond %{REQUEST_URI} ^/.well-known/acme-challenge/ [NC]
RewriteRule ^ - [L]

それ以外は HTTPS 強制 & 正規ドメイン以外拒否

RewriteCond %{HTTP_HOST} !^(www.|pacific.)?sky.0t0.jp$ [NC,OR]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ %{REQUEST_URI} [R=301,L]

結果

dry-run で無事に通過!

実際の更新でもエラー無し

sendmail や Web サーバーも証明書更新後に自動リロードする仕組みなので安心

そして気づいたのは、preferred-challenges = http は実は不要だったこと。
webroot で .well-known/acme-challenge/ が適切に処理されるなら、certbot は自動的に http-01 を選んでくれるのです。

まとめ

・443 を塞いでも問題なし

・80 を世界に開ける代わりに acme-challenge だけ例外にすればOK

・certbot は自動で http-01 を使ってくれるので、余計な設定は不要

結果的に、
「海外ストーカー対策は維持しつつ、証明書更新も安定」
という理想の形になりました(笑)