A previous version of this tutorial was written by Sergey Zhukaev.
はじめに
Nginx は高速で信頼性のあるオープンソースのウェブサーバーです。低メモリフットプリント、高いスケーラビリティ、設定の容易さ、およびさまざまなプロトコルのサポートによって人気を博しました。
HTTP/2は、サーバーからブラウザへのページの配信に使用されるハイパーテキスト転送プロトコルの新しいバージョンです。HTTP/2は、HTTPの大きな更新版であり、ほぼ20年ぶりのものです。HTTP1.1は、ウェブページがはるかに小さかった1999年に一般に公開されました。その後、インターネットは大きく変化し、今ではHTTP 1.1の制限に直面しています。このプロトコルは、ほとんどの現代のウェブサイトの潜在的な転送速度を制限します。なぜなら、ページの一部がキューでダウンロードされるためです。前の部分が完全にダウンロードされるまで、次の部分のダウンロードが開始されません。そして、平均的な現代のウェブページは、数十の個々のCSS、JavaScript、および画像リソースをダウンロードします。
HTTP/2は、いくつかの基本的な変更をもたらすことでこの問題を解決します。
- すべてのリクエストが順番ではなく並行してダウンロードされます。
- HTTPヘッダーは圧縮されます。
- ページはテキストファイルではなくバイナリとして転送され、これが効率的です。
- サーバーはユーザーの要求なしにデータを「プッシュ」でき、これによりレイテンシの高いユーザーの速度が向上します。
HTTP/2は暗号化を必要としませんが、2つの最も人気のあるブラウザ、Google ChromeとMozilla Firefoxの開発者は、セキュリティ上の理由からHTTP/2をHTTPS接続のみサポートすると述べています。したがって、HTTP/2をサポートするサーバーを設定する場合は、HTTPSでセキュリティを確保する必要があります。
このチュートリアルでは、HTTP/2をサポートする高速かつ安全なNginxサーバーのセットアップ方法を紹介します。
前提条件
始める前に、いくつかのものが必要です:
- Ubuntu 22.04サーバーが設定されている必要があります。これは、Ubuntu 22.04初期サーバーセットアップガイドに従って、sudo非ルートユーザーとファイアウォールを含めて設定できます。
- サーバーにNginxがインストールされている必要があります。これは、Ubuntu 22.04にNginxをインストールする方法に従って行うことができます。
- A domain name configured to point to your server. You can purchase one on Namecheap or get one for free on Freenom. You can learn how to point domains to DigitalOcean Droplets by following the documentation on How To Manage Your Domain With DigitalOcean.
- A TLS/SSL certificate configured for your server. You have two options:
- Let’s Encryptから無料の証明書を取得することができます。これは、Ubuntu 22.04でLet’s Encryptを使用してNginxをセキュリティ保護する方法に従って行うことができます。
- あなたはUbuntu 22.04でNginxのための自己署名SSL証明書を作成する方法に従って、自己署名証明書を生成して構成することもできます。
- Nginxはポート
80
からポート443
へのトラフィックのリダイレクトが構成されている必要があります。これは前提条件を満たすべきです。 - Nginxは2048ビット以上のエフェメラルDiffie-Hellman(DHE)キーを使用するように構成されている必要があります。これも前提条件を満たすべきです。
ステップ1 — HTTP/2サポートの有効化
Nginxのインストールチュートリアルでサーバーブロックの設定手順に従っている場合、/etc/nginx/sites-available/your_domain
にドメインのサーバーブロックがあり、server_name
ディレクティブがすでに適切に設定されているはずです。最初の変更は、ドメインのサーバーブロックをHTTP/2を使用するように変更することです。
お好みのエディタで、ドメインの構成ファイルを開きます(例:nano
):
ファイルで、ポート443
に関連付けられたlisten
変数を見つけます:
...
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
...
最初のものはIPv6接続用です。2番目のものはすべてのIPv4接続用です。両方でHTTP/2を有効にします。
各listen
ディレクティブを変更してhttp2
を含めます:
...
listen [::]:443 ssl http2 ipv6only=on;
listen 443 ssl http2;
...
これにより、NginxがサポートされるブラウザでHTTP/2を使用するように指示されます。
構成ファイルを保存してテキストエディタを終了します。 nano
を使用している場合は、Ctrl+X
を押してから、プロンプトが表示されたらY
を押してからEnterキーを押します。
Nginxの構成ファイルを変更するときは、-t
フラグを使用して構成エラーをチェックする必要があります。これは、Nginxの組み込み構文チェックコマンドを実行します:
構文にエラーがない場合、次のような出力が表示されます:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
次に、Nginxサーバーをより制限の多い暗号リストを使用するように構成します。サーバーのセキュリティを向上させます。
ステップ2 — 古くて安全ではない暗号スイートの削除
HTTP/2には、回避すべき古くて安全でない暗号のブロックリストがあります。 暗号スイートは、転送されるデータを暗号化する方法を記述する暗号化アルゴリズムです。
使用する方法は、NginxのTLS/SSL証明書をどのように構成したかによって異なります。
Certbotを使用して証明書を取得した場合、次のファイルが作成されます:/etc/letsencrypt/options-ssl-nginx.conf
。このファイルには、HTTP/2には十分に安全でない暗号が含まれています。ただし、このファイルを変更すると、将来的なCertbotの更新が適用されなくなるため、Nginxにこのファイルを使用しないよう指示し、独自の暗号リストを指定します。
ドメインのサーバーブロック構成ファイルを開きます:
sudo nano /etc/nginx/sites-enabled/your_domain
options-ssl-nginx.conf
ファイルが含まれる行を探し、行の先頭に#
文字を追加してコメントアウトします:
# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
その行の下に、許可される暗号を定義するために次の行を追加します:
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ファイルを保存してエディタを終了します。
自己署名証明書を使用したり、サードパーティから証明書を取得し、前提条件に従って構成した場合は、テキストエディタで次のファイルを開きます:/etc/nginx/snippets/ssl-params.conf
:
次の行を探します:
...
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
...
それを次の暗号リストを使用するように変更します:
...
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ファイルを保存してエディタを終了します。
再度、nginx -t
コマンドを使用して構成の構文エラーを確認します:
エラーが発生した場合は、それらを修正して再度テストします。
構成が構文チェックをパスしたら、systemctl
コマンドを使用してNginxを再起動します:
サーバーが再起動したら、動作することを確認しましょう。
ステップ3 — HTTP/2が有効になっていることの確認
サーバーが実行され、HTTP/2と連携していることを確認しましょう。
curl
コマンドを使用して、サイトにリクエストを行い、ヘッダーを表示します:
以下のような出力が表示されます:
HTTP/2 200
**Server**: nginx/1.18.0 (Ubuntu)
**Date**: Tue, 21 Jun 2022 22:19:09 GMT
**Content-Type**: text/html
**Content-Length**: 612
**Last-Modified**: Tue, 21 Jun 2022 22:17:56 GMT
**Connection**: keep-alive
**ETag**: "62b24394-264"
**Accept-Ranges**: bytes
また、HTTP/2が使用されているかをGoogle Chromeで確認することもできます。Chromeを開き、https://your_domain
に移動します。Chromeの開発者ツールを開きます (表示 -> 開発 -> 開発ツール) 、そしてページをリロードします (表示 -> このページを再読み込み) 。ネットワークタブに移動し、Nameで始まるテーブルヘッダー行を右クリックし、ポップアップメニューからプロトコルオプションを選択します。
新しいプロトコル列が表示され、HTTP/2を示すh2
が含まれています。これにより、HTTP/2が動作していることが示されます。
この時点で、HTTP/2プロトコルを通じてコンテンツを提供する準備が整いました。HSTSを有効にしてセキュリティとパフォーマンスを向上させましょう。
ステップ4 — HTTP Strict Transport Security(HSTS)の有効化
HTTPリクエストがHTTPSにリダイレクトされている場合でも、HTTP Strict Transport Security(HSTS)を有効にして、そのリダイレクトを行わなくてもよくなります。ブラウザがHSTSヘッダーを見つけると、一定期間、サーバーに通常のHTTP経由で接続しようとしません。常に暗号化されたHTTPS接続のみでデータを交換します。このヘッダーはまた、プロトコルのダウングレード攻撃からも保護します。
ドメインのサーバーブロック構成ファイルを再度開きます:
sudo nano /etc/nginx/your_domain
次の行をSSL暗号を含むファイルの同じブロックに追加して、HSTSを有効にします:
server {
...
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
add_header Strict-Transport-Security "max-age=15768000" always;
}
...
max-age
は秒単位で設定されます。値15768000
は6ヶ月に相当します。
デフォルトでは、このヘッダーはサブドメインのリクエストに追加されません。サブドメインがあり、すべてのサブドメインにHSTSを適用したい場合は、行の最後にincludeSubDomains
変数を追加してください。次のようになります:
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
ファイルを保存し、エディターを終了します。
構文エラーがないかを再度確認します:
最後に、変更を適用するためにNginxサーバーを再起動します。
結論
あなたのNginxサーバーは今、HTTP/2ページを提供しています。SSL接続の強度をテストしたい場合は、Qualys SSL Labを訪れ、サーバーに対してテストを実行してください。すべてが適切に構成されている場合、セキュリティに関してA+の評価を受けるはずです。
Nginxがサーバーブロックルールを解析および実装する方法について詳しく知りたい場合は、Nginxサーバーおよびロケーションブロック選択アルゴリズムの理解を読んでみてください。