NginxのHTTP/3設定手順

isdはじめに

当「稲葉サーバーデザイン」サイトはもともとHTTP/2に対応していましたが、NginxがHTTP/3に対応したことがわかったので、当サイト向けに設定してみました。

ここでは、RHEL系LinuxサーバーでのNginxのHTTP/3設定手順と、注意点について記載します。
HTTP/3そのものの説明や、NginxやSSL証明書の基本的な設定については記載しません。

HTTP/3の理解とNginxでの設定については、以下の記事を参考にしました。
ありがとうございます。

(参考)
・Nginx の HTTP/3 対応を完全に理解する – GMO INTERNET GROUPグループ研究開発本部ブログ
https://recruit.gmo.jp/engineer/jisedai/blog/nginx-http-3/

・HTTP/3 の特徴 HTTP/2とQUICの違い – キャッシュ屋blog
https://blog.redbox.ne.jp/http3-quic.html

・Webサイトの表示速度をさらに高速化!「HTTP/3」とは? – さくらのSSL
https://ssl.sakura.ad.jp/column/http3/

・nginxでQUIC+HTTP/3対応Webサーバを構築する – Zenn
https://zenn.dev/novenove/articles/ffb61d96393495

・nginxでHTTP/3を使う方法 2023年5月版 – Zenn
https://zenn.dev/catatsuy/articles/71609eff5611e4

isdHTTP/3の対応手順

当サイトのサーバーOSはRocky Linux 8、WebサーバーはNginxを使用しています。
このサーバーでは、HTTP/3の対応として、大きく以下の3つが必要でした。

  1. ファイアウォールでUDP/443ポートをアクセス許可
  2. Nginxのアップデート
  3. NginxのVirtualHost設定

1. ファイアウォールでUDP/443ポートをアクセス許可

HTTP/3は、従来のHTTPSのTCP/443ポートではなく、UDP/443ポートを使用します。
そのため、ファイアウォールで、インバウンド通信のUDP/443ポートのアクセス許可ルールを追加します。

2. Nginxのインストールまたはバージョンアップ

Nginxは、バージョン1.25以降でHTTP/3に対応していますので、1.25以降のバージョンにアップグレードします。

(参考)
・Support for QUIC and HTTP/3 – Nginx公式
http://nginx.org/en/docs/quic.html

サーバーではもともと、Rocky Linux 8リポジトリが配布するNginxを使用し、バージョンは1.24でした。
Nginx公式サイトを確認すると、Nginx公式による nginx-mainline リポジトリが配布するRPMのバージョンは1.25であることがわかります。
ですので、nginx-mainline リポジトリのNginx 1.25をインストール(アップデート)することにします。

・nginx: download – Nginx公式
http://nginx.org/en/download.html

・nginx: Linux packages – Nginx公式
http://nginx.org/en/linux_packages.html

(余談ここから)
インターネット上の少し古い記事では、
「Nginxのソースをダウンロードしてビルド」
のような設定手順が出てきますが、それらは、NginxがHTTP/3に対応した直後の時期のものが多いです。
現在はバージョン1.25のRPMが配布されていますので、自分でビルドする必要はありません。
(もちろん、自分でビルドしても構いません。)
また、配布されているRPMは、OpenSSLを静的リンクしてビルドされていますので、現在サーバーにインストールされているOpenSSLのバージョンを気にする必要もありません。
(余談ここまで)

nginx-mainline リポジトリを追加して有効化(enable=1)します。

 # vim /etc/yum.repos.d/nginx.repo

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

 

dnfコマンドで、(すでにインストール済みの)Nginxをアップデートします。

 # dnf update nginx

--
...
アップグレード済み:
  nginx-1:1.25.4-1.el8.ngx.x86_64
--

 

アップデートされたNginxの情報を確認します。

 # nginx -V

nginx version: nginx/1.25.4
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-18) (GCC)
built with OpenSSL 1.1.1k  FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie

 

↑バージョンは 1.25.4、ビルド時のオプションで --with-http_v3_module として、HTTP/3モジュールが含まれていることがわかります。

NginxのVirtualHost設定

VirtualHostの箇所で、HTTP/3用に設定を変更します。
以下、HTTP/2, HTTP/3に関連する設定のみ抜粋します。

 # vim /etc/nginx/conf.d/vhost_ssl_inaba-serverdesign.jp.conf

 

-- 変更前
server {
    listen      443 ssl http2;

    server_name inaba-serverdesign.jp;

    ssl_protocols TLSv1.2 TLSv1.3;
...
--

 

-- 変更後
server {
    listen      443 ssl;
    listen      443 quic reuseport;
    http2       on;
    http3       on;
    add_header  Alt-Svc 'h3=":443"; ma=86400';

    server_name inaba-serverdesign.jp;

    ssl_protocols TLSv1.2 TLSv1.3;
...
--

 

ポイントは4箇所。

  • listen 443 quic reuseport;
  • http3 on;
  • add_header Alt-Svc ‘h3=”:443″; ma=86400’;
  • ssl_protocols TLSv1.2 TLSv1.3;

以下、補足します。

listen      443 quic reuseport;

443ポートで、HTTP/3通信で使用するQUICプロトコルを受け付けるようにし、reuseportでポートを複数のプロセスから利用できるようにします。
 

http3       on;

HTTP/3を有効にします。
 

add_header  Alt-Svc 'h3=":443"; ma=86400';

Alt-Svcヘッダーで、ポート443でHTTP/3に対応していることを示します。
ma=86400 は、このヘッダーの有効期限が86400秒=24時間であることを意味します。
 

ssl_protocols TLSv1.2 TLSv1.3;

QUICプロトコルはTLSv1.3が必須のため、SSL(TLS)プロトコル指定でTLSv1.3を指定します。
クライアントがTLSv1.3に非対応の場合もあるので、TLSv1.2も指定します。

また、クライアントがHTTP/3に非対応の場合もあるので、HTTP/2も許可します。
Nginx 1.25から、HTTP/2の有効化は、listenディレクティブではなく、http2ディレクティブで指定するようになりました。

    listen      443 ssl;
...
    http2       on;

Nginx Configの文法をチェックします。
 

 # nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

 

エラーがあれば対応し、問題なければNginxをreloadして反映します。

 # systemctl reload nginx

 

isdHTTP/3の動作確認

Webブラウザで、ページが正しく表示されることを確認します。
また、ブラウザのDeveloperToolsなどで、通信プロトコルが HTTP/3 となっていることを確認します。
Chrome DeveloperToolsでは、以下のように Protocols 列で h3 と表示されます。

また、HTTP/3 Checkサイトで確認するのもよいでしょう。
https://http3check.net/

当サイトはご覧のとおりシンプルなつくりですので(笑)、残念ながら「体感としてページ表示が速くなった」ということはありません。

isdHTTP/3対応で発生した不具合

実施したNginxのHTTP/3対応で、一部、以下のような不具合が発生しました。

  • 他のVirtualHostサイトが正しく表示されない。
  • Redmineのログイン、ログアウト後のページ遷移がおかしい。

補足します。

  • 他のVirtualHostサイトが正しく表示されない。

1台のサーバーで複数ドメインの複数サイトを運用するケースは多いと思います。
NginxのName VirtualHost環境で、複数のVirtualHostでreuseportを指定すると、Nginxを起動するときに
「duplicate listen options for 0.0.0.0:443 in /etc/nginx/conf.d/example.conf:4」
というようなエラーとなります。

この問題の対策としては、
「複数のサイトをHTTP/3に対応するには、reuseportは1つのVirtualHostのみ指定するとよい」
という情報があります。

(参考)
・nginx で バーチャルドメインを同一IPアドレスでhttp/3(QUIC) 運用する方法 – Qiita
https://qiita.com/iscream/items/bd47ba2c13631bfdd2d5

この方法を試してみたのですが、、、
うちのサーバー環境では、reuseportを指定しないドメインのサイトについて、以下の不具合が発生しました。

  • 表示が崩れる。
  • 本来のドメインとは異なる、reuseportを指定したドメインのサイトページが表示される。

とくに、後者の別サイトのページが表示されるのは致命的ですね。
このため、ひとつのVirtualHostのみHTTP/3とし、それ以外はHTTP/2のままとしました。
NginxのProxyCacheやPHP-FPMへのリバースプロキシが影響しているのかも?とは思いましたが、「どうしても全サイトHTTP/3に対応したい」というほどでもないので、現時点ではこれ以上の調査はしません。

  • Redmineのログイン、ログアウト後のページ遷移がおかしい。

これは別のサーバーでの現象ですが、プライベート環境で使用しているRedmineで、
「ログインおよびログアウト時に https://localhost/~ にリダイレクトアクセスしようとしてしまう」
という現象が発生しました。
ログイン後は、再度アクセスすると、ログインは完了した状態でページが表示されるので、認証処理が通ったあとのページ遷移時に、HTTPホスト名が localhost に変わってしまうようです。
FCGIへのリバースプロキシが影響しているような気がしましたが、こちらも特にこだわりはないので、現時点ではあきらめてHTTP/2のままとしています。

このように、思わぬ箇所で不具合が発生するケースもありそうなので、トップページだけではなく、認証、更新、ページ遷移など、しっかり動作確認されることをおすすめします。

isdおわりに

NginxでのHTTP/3設定手順と、発生した不具合について記載しました。

Nginxリポジトリの配布パッケージにもすでに反映されているのでインストールが簡単ですし、設定もシンプルですので、比較的簡単に導入できますので、興味のある方は試してみるとよいと思います。
うまくいかなければ、簡単にOFFにできますし。

当サイトでは劇的な効果は見られませんでしたが、ページあたりのリクエスト数が多いサイトでは効果がありそうです。
ただし、思わぬ箇所で不具合が発生する可能性もありそうなので、動作確認はしっかり実施することをおすすめします。

今回はNginxで設定しましたが、ApacheはまだHTTP/3に対応してないようです。
Apacheを使用しつつHTTP/3に対応したいときは、Apacheの前段にリバースプロキシ用Nginxを設置するのが、ひとつの解決方法になると思います。

(参考)
・Apacheの前段にNginxリバースプロキシサーバーを設置
https://inaba-serverdesign.jp/blog/20230411/nginx_reverseproxy_apache_wordpress.html

 

Follow me!