「NginxのSSL証明書とHTTPSリダイレクトのエラーについて」
イントロダクション
Nginxは多くの大規模で高トラフィックのサイトをインターネット上でホストできる人気のあるウェブサーバーです。Nginxをインストールした後、ウェブサイトはデフォルトでHTTPトラフィックのリクエストを受け付けます。これはウェブサイトにとって最も安全なオプションではありません。そのため、HTTPトラフィックをHTTPSにリダイレクトすることを選択することができます。HTTPSは暗号化されたトラフィックであり、TLS/SSL証明書で確認されます。Let’s EncryptやCerbotなどのリソースを使用することで、証明書の取得やHTTPSへのリダイレクトのプロセスを自動化することができますが、Nginxウェブサーバーではまだエラーが発生する可能性があります。
このガイドの例はUbuntu 22.04サーバーでテストされましたが、ほとんどのNginxインストールに適用することができます。これらのエラーのほとんどは、Nginxの標準化された設定ファイルの範囲内で解決できますが、ディレクトリやパスは若干異なる場合もあります。
このチュートリアルでは、NginxサーバーのTLS/SSL証明書とHTTPSリダイレクト接続の設定時に発生する一般的なエラーについて学びます。また、これらのリダイレクトエラーの可能な原因を特定し、修正する方法も学びます。
あなたのNginxエラーログの検査
このチュートリアルで提示されるエラーや解決策は一般的な例であり、すべての可能性を網羅しているわけではありません。構文エラーがNginxが正規の文と認識する構造を崩すため、以下のエラーはNginxの応答方法のガイドラインに過ぎません。しばしば、1つのエラーが別のエラーを引き起こすことがあり、エラーはより大きな問題や別の問題の症状となる場合もあります。特定の状況やセットアップによって状況は異なる可能性があります。
常にNginxエラーログを参照して実行中のリストを表示できることに注意してください。
- sudo cat /var/log/nginx/error.log
サーバーブロックのリダイレクトディレクティブを確認してください。
もしウェブサイトがHTTPからHTTPSへのリダイレクトがうまく行っていない場合、設定ファイルに設定したディレクティブに問題がある可能性があります。具体的には、listenディレクティブが適切なポート(この場合、443)を指定しているかどうかが重要です。このポートは暗号化されたHTTPSトラフィックを示します。なお、Nginxウェブサーバーのサーバードメインのブロックを設定する場合、以下の構造に従う可能性があります。
/example.com の例となる場所にある /etc/nginx/sites-availableのファイル
server {
listen 80;
listen [::]:80;
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
}
このファイルの内容には、いくつかの指示の詳細が記載されていますが、特に注意すべき重要な指示は「listen」です。現在、この指示ではポート80への受信リクエストのみを許可していますが、これはNginxのデフォルトのポートです。このポートはHTTPトラフィック用であり、HTTPSではありません。HTTPトラフィックをHTTPSにリダイレクトするためには、listen指示を更新してポート443を含める必要があります。
効率的にこれを行う方法の一つは、Let’s Encryptのような証明書発行局(Certificate Authority、CA)からTLS/SSL証明書を取得することです。ウェブサーバーに対して暗号化されたHTTPSを可能にするために、ウェブサイトに証明書を持つことが役立ちます。
さらに、Certbotというソフトウェアクライアントを使用して、Nginx向けの証明書の取得とインストールを完全に自動化することもできます。このCertbotにはNginx用のプラグインが備わっており、CertbotにNginxの設定ファイルを自動的に構成させて、すべてのHTTPトラフィックをHTTPSにリダイレクトし、直接のHTTPトラフィックを禁止することもできます。もちろん、好みに応じて手動で行うこともできますし、同じ原則が適用されます。詳しくは、当社の「Let’s EncryptでNginxをセキュアにする方法」のチュートリアルをご参照ください。なお、このチュートリアルでは、Let’s Encryptを通じて証明書を取得し、設定ファイルが次のように更新されています。
以下のフレーズを日本語で言い換えます:
「/etc/nginx/sites-available/example.com」
server {
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
もし最初の例とこのサーバドメインブロックを比較すると、Certbotによって管理された自動手順の結果として行われた変更を評価することができます。さらに重要なのは、listenディレクティブがポート443を指しているため、HTTPS接続が許可されるということです。Certbotを通じてLet’s Encryptが生成した証明書と鍵も、今やあなたのサーバブロックと関連付けられています。
さらに、Certbotはサーバーブロックを再構築して、すべてのHTTPトラフィックをHTTPSにリダイレクトします。今、追加のサーバーブロックがありますが、これはポート80での元のリッスン指令を処理します。この新しいサーバーブロックは、$host変数に対する条件付きチェックを行うことで、ドメインへのすべてのトラフィックをキャッチします。このチェックは条件付きのif指示文で実行されます。これらの指示文は、変数がドメインと一致するかどうかをチェックし、それからNginxは301リダイレクトを使用してリクエストをサイトのHTTPSバージョンに送信します。さらに、重要なのは、条件付きリダイレクトを通過してトラフィックが届いた場合、ホストされていないエラーページとして404エラーになります。
もしまだ問題が続く場合は、ファイアウォールの設定を確認し、必要に応じて調整してみてください。
ファイアウォールの設定の調整
WebブラウザがTLS/SSL証明書の設定を行っても応答しない場合、ファイアウォールの設定に問題がある可能性があります。前のセクションで述べたように、Let’s Encryptチュートリアルに従った場合、HTTPからHTTPSへのリダイレクトは自動的に構成ファイルのリスンディレクティブとして設定されます。したがって、エラーの原因の1つとして、ファイアウォールがポート443上のHTTPSトラフィックを許可していない可能性があります。
現在ファイアウォールで開かれているポートの状態を確認するには、次のコマンドを実行します。ただし、このチュートリアルはUncomplicated Firewall(UFW)を使用しているため、配布されているディストリビューションによって異なる場合があります。
- sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
以下のようなリストが表示されれば、現在のファイアウォールはHTTPからのリクエストのみを受け付けるように設定されています。これらの設定を調整するためには、ポート443を介してTLS/SSLで暗号化されたトラフィックを許可するNginx HTTPSプロファイルを追加する必要があります。これを行うには、以下のコマンドを実行してください。
- sudo ufw allow ‘Nginx HTTPS’
もし「ルールが追加されました」という出力を受け取ったら、このプロフィールをリストに正常に追加できたことを確認できます。ステータスをチェックして確認してください。
- sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
Nginx HTTPS ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
Nginx HTTPS (v6) ALLOW Anywhere (v6)
Note
sudo ufw allow ‘Nginx Full’
ファイアウォールは、HTTPとHTTPSトラフィックからの接続を受け入れる準備が整いました。
今では、NginxのHTTPおよびHTTPSプロファイルが両方リストに表示され、ポート443が開放されています。そして、リクエストはHTTPSにリダイレクトされます。
TLS/SSL証明書を使用して、安全にリダイレクトを設定する
HTTPからHTTPSへのリダイレクトは、暗号化されたトラフィック接続を許可することを意味します。通常、これはTLS / SSL証明書で検証されます。しかし、ブラウザレベルでまだエラーメッセージが発生する可能性があります。これらのエラーメッセージは、Nginxサーバーに問題があるわけではなく、むしろ証明書そのものに問題があることを意味していることを忘れないでください。
例えば、自己署名SSL証明書を使用している場合、それはLet’s Encryptのような証明機関(CA)によって検証されません。その結果、https://example.comにブラウザでアクセスすると、訪問者に対してこのサイトは安全ではないという警告メッセージが表示される可能性があります。
このシナリオでは、「接続がプライベートではない」というエラーが発生し、NET::ERR_CERT_AUTHORITY_INVALIDという具体的なエラーが表示されます。証明書が安全でなくても、[高度な設定]オプションを選択すればこれを回避することができます。
「Advanced(高度な)」オプションの詳細によると、example.comは適切に識別できないとされています。自己署名SSL証明書でウェブサーバーを設定しているため、これが実際に真実であるとは限りませんが、あなたのサイトを訪れる人々にはこのように捉えられる可能性があります。
「先へ進む」オプションを押すことでウェブサイトに進むことができますが、訪れた際にこのようなセキュリティとプライバシーのメッセージが表示されると、ユーザーエクスペリエンスは悪くなります。CAによって検証された証明書を使用することがおすすめです。Let’s Encryptと共にNginxをセキュアにする方法については、当社のチュートリアルを参照して設定することができます。
ただし、Let’s Encryptを通じてTLS/SSL証明書が設定されている場合でも、以下のメッセージが表示される可能性があります。
オリジナルの「接続がプライベートではありません」というメッセージとは異なり、このメッセージはNET::ERR_CERT_DATE_INVALIDというネットワークエラーが表示されます。これは、現在のSSL/TLS証明書が期限切れであることを意味します。Let’s Encryptの証明書は90日間しか有効ではないことに注意してください。Let’s Encryptをインストールする際にcertbotパッケージを使用した場合、次の30日以内に期限切れの証明書があるかどうかを確認するスケジュールが設定され、systemdを通じて一日に二回実行されます。
以下の方法でタイマーの状態を確認できます。
- sudo systemctl status snap.certbot.renew.service
出力が、証明書の更新が有効であることを確認します。
ただし、証明書が期限切れになっており、強制的に更新したい場合は、次のコマンドを使用することができます。また、異なるドメインで証明書を更新したい場合にも役立ちます。
- certbot certonly –force-renew -d example.com
Certbotパッケージには、/etc/cron.dに証明書の更新スクリプトが付属していますが、他のオプションもあります。例えば、Certbotでrenew_hookオプションを設定することで、更新後に他のタスクを実行することができます。これを行うためには、Certbotの更新設定ファイルにrenew_hookを追加する必要があります。お好みのテキストエディタでファイルを開いてください。
- sudo nano /etc/letsencrypt/renewal/example.com.conf
ファイル内に入ったら、最後の行にフックを追加して、更新された証明書を使用するようにウェブサービスを再読み込みして設定できるようにします。
以下のテキストを日本語で表現する場合、次のように言い換えることができます。
「/etc/letsencrypt/renewal/example.com.conf」
renew_hook = systemctl reload your_service
作業が終了したら、ファイルを保存して閉じることができます。もしnanoを使っている場合は、CTRL + X、Y、そしてENTERを押してください。
証明書の更新プロセスを設定する際に選択するものに関わらず、次のコマンドを使用してcertbotが正常に更新プロセスを実行していることを常に確認できます。
- sudo certbot renew –dry-run
最後に、sudo nginx -t を使用して構文エラーをチェックし、その後、sudo systemctl restart nginx を使用してNginxを再起動して変更が反映されることを確認してください。これらすべてを行った後、https://example.com にアクセスして、リダイレクトが正常に動作していることを確認してください。
結論
このチュートリアルでは、Nginxウェブサーバーリダイレクトの一般的なエラーについて学びました。具体的には、HTTPからHTTPSへのリダイレクトに関するエラーの対処方法について説明しました。これらの解決策には、適切なポートでの待ち受けが正しく設定されているかを確認すること、ファイアウォールを開いてこれらの接続を受信する方法、およびSSL/TLS証明書が検証されていないか有効期限切れであるかに関するセキュリティエラーメッセージの処理方法が含まれています。Nginxについてもっと学びたい場合は、当社のタグ付けされたコミュニティページをチェックするか、Ubuntu 22.04にNginxをインストールする方法の学習に進んでみてください。