NginxをHTTPSで保護する:ステップバイステップガイド
この包括的なステップバイステップガイドでは、NginxウェブサーバーをHTTPSで保護する方法を学びます。Certbotを使用してLet's Encryptから無料のSSL/TLS証明書を取得し、暗号化接続用にNginxを設定し、HSTSなどの必須セキュリティ対策を実装する方法を解説します。適切に設定されたHTTPSでデータを保護し、ユーザーの信頼を築き、SEOを向上させましょう。
NginxをHTTPSで保護する:ステップバイステップガイド
NginxをHTTPSで保護するのは通常小さな作業ですが、小さなミスが大きな影響を及ぼす作業の一つです。証明書ファイルが欠けているとNginxのリロードが失敗します。ファイアウォールルールを忘れるとサイトがダウンしているように見えます。急いでHSTSヘッダーを設定すると、ユーザーが意図したよりも長く壊れたHTTPS設定にロックされる可能性があります。
良いニュースは、通常の手順はシンプルだということです。DNSをサーバーに向け、Nginxがポート80で応答することを確認し、Certbotを使用してLet's Encrypt証明書をリクエストし、生成されたNginx設定をテストし、リロードしてから更新を確認します。このガイドではその手順に従います。
以下ではexample.comとwww.example.comを使用します。実際の名前に置き換え、Nginxをリロードする前のチェックを省略しないでください。
証明書をリクエストする前に
Certbotに触れる前に、基本的な部分を確認してください。ほとんどの証明書の問題は、DNS、ファイアウォール、またはリクエストされたドメインに応答しないサーバーブロックから発生します。
サーバーの外部からDNSを確認します:
dig +short example.com
dig +short www.example.com
両方の名前が、Nginxホストまたはロードバランサーに到達するパブリックアドレスに解決される必要があります。
ポート80と443がすべてのレイヤー(クラウドセキュリティグループ、ホストファイアウォール、ネットワークファイアウォール、およびホストの前にあるロードバランサー)で開いていることを確認します。
sudo ss -tulnp | grep nginx
sudo ufw status
クラウドVMでは、プロバイダーのコンソールも確認してください。インスタンスファイアウォールが443を許可しているが、クラウドセキュリティグループがまだブロックしているために、きれいなNginx設定が失敗するのを何度も見てきました。
最後に、NginxがプレーンHTTPでドメインを提供していることを確認します:
curl -I http://example.com
curl -I http://www.example.com
応答はきれいである必要はありません。プレースホルダーページでも構いません。そのホスト名へのリクエストがこのNginxサーバーに到達することを証明するだけで十分です。
Certbotのインストール
Debian/Ubuntuの場合:
sudo apt update
sudo apt install certbot python3-certbot-nginx
RHEL互換システムの場合:
sudo dnf install certbot python3-certbot-nginx
古いCentOSシステムではyumを使用し、最初にEPELを有効にする必要がある場合があります。パッケージ名もディストリビューションのバージョンによって異なるため、これらのコマンドでプラグインが見つからない場合は、ディストリビューションのパッケージドキュメントを使用してください。
証明書のリクエスト
Nginxプラグインは証明書をリクエストし、一致するサーバーブロックを編集できます:
sudo certbot --nginx -d example.com -d www.example.com
Certbotはメールアドレス、利用規約への同意、およびHTTPをHTTPSにリダイレクトするかどうかを尋ねます。通常の公開ウェブサイトの場合はリダイレクトを選択してください。APIや内部サービスの場合は、最初にクライアントを確認してください。一部の古いクライアントやヘルスチェックは、まだhttp://を呼び出し、特定の応答を期待する場合があります。
Certbotが一致するサーバーブロックを見つけられないと言った場合は、server_nameを確認してください。次のようなブロックは、Certbotが明確に処理できるものを提供します:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Certbotに何かを編集させる前に、構文チェックを実行します:
sudo nginx -t
現在の設定がすでに壊れている場合は、最初にそれを修正してください。
Nginx設定の理想的な形
成功した実行後、通常はHTTPをリダイレクトするブロックとHTTPSでサイトを提供するブロックの2つが表示されます:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/example.com/public;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
これを本番設定に盲目的にコピーしないでください。既存のlocationルール、プロキシ設定、ログ、アップロード制限を保持してください。重要な部分は、listen 443 ssl、証明書のパス、およびポート80でのリダイレクト動作です。
テスト、リロード、確認
リロードする前に必ずテストします:
sudo nginx -t
次にリロードします:
sudo systemctl reload nginx
コマンドラインから確認します:
curl -I http://example.com
curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
HTTPリクエストは、そのオプションを選択した場合にリダイレクトされるはずです。HTTPSリクエストは期待されるステータスを返すはずです。opensslコマンドは、サブジェクトまたはサブジェクト代替名がドメインをカバーし、日付が現在のものである証明書を表示するはずです。
ブラウザでのテストも重要です。プライベートウィンドウでサイトを開き、ロックアイコンをクリックして証明書を確認します。サイトが古いhttp:// URLからアセットを読み込んでいる場合、メインの証明書が正常でも、ページに混合コンテンツの警告が表示されることがあります。アプリ、CMS、またはテンプレートレイヤーでそれらのアセットURLを修正してください。
更新
Let's Encrypt証明書は有効期間が短いため、自分で覚えていなくても更新が機能する必要があります。Certbotは通常、systemdタイマーまたはcronジョブをインストールします。確認します:
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
ドライランが有用な部分です。更新シミュレーションを実行し、壊れたHTTP検証、DNS変更、欠落したプラグイン、またはリロードできない設定などの一般的な問題をキャッチします。
Nginxホストで直接ではなく、ロードバランサーやCDNでTLSを終端する場合、更新にはDNSチャレンジや異なるデプロイパスが必要になる場合があります。パブリックトラフィックがこのサーバーに到達しない場合、デフォルトのHTTPチャレンジが機能するとは想定しないでください。
確認すべきTLS設定
ほとんどの最新の公開サイトでは、TLS 1.2とTLS 1.3が実用的なベースラインです:
ssl_protocols TLSv1.2 TLSv1.3;
理由がわからない限り、暗号リストを手動で調整しないでください。Certbotに含まれているoptions-ssl-nginx.confとMozilla SSL Configuration Generatorは、古いブログ記事からコピーした暗号文字列よりも優れた出発点です。暗号のガイダンスは時間とともに変化し、互換性の要件は公開マーケティングサイトと内部レガシーAPIで異なります。
HSTSは便利ですが、注意が必要です:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
テスト中は短い値から始めます:
add_header Strict-Transport-Security "max-age=300" always;
すべてのサブドメインが有効なHTTPSを提供できる場合にのみincludeSubDomainsを使用してください。old.example.com、mail.example.com、または顧客固有のサブドメインが準備できていない場合、そのオプションは実際のユーザーを壊す可能性があります。
よくある失敗
Certbotがドメインを検証できない場合、最初にDNS、次にポート80、次にNginxサーバーブロックを確認してください。HTTP-01チャレンジでは、Let's Encryptが/.well-known/acme-challenge/の下のトークンに到達する必要があります。リダイレクトは正しく設定されていれば問題ありませんが、プロキシ、CDN、またはキャッチオールブロックが誤ってチャレンジを別の場所に送信する可能性があります。
Certbotの変更後にNginxのリロードが失敗した場合、次を実行します:
sudo nginx -t
sudo journalctl -u nginx -n 80 --no-pager
構文テストは通常、正確なファイルと行を教えてくれます。一般的な原因は、重複したlisten 443 sslブロック、削除された証明書パス、またはこのサーバーに存在しないパスからインクルードされたスニペットです。
HTTPSがローカルでは機能するがユーザーには機能しない場合、パブリックパスを確認してください。ロードバランサーが古いターゲットグループを指している可能性があります。CDNがリダイレクトをキャッシュしている可能性があります。IPv6 DNSがIPv4とは異なるホストを指している可能性があります。両方をテストします:
curl -4 -I https://example.com
curl -6 -I https://example.com
最もクリーンなHTTPS設定は退屈です:DNSが正しい場所を指し、Nginxにドメイン用の明確なサーバーブロックが1つあり、Certbotの更新がドライランで成功し、基本が機能した後にのみヘッダーが追加されます。