はじめに
当「稲葉サーバーデザイン」サイトはもともと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
HTTP/3の対応手順
当サイトのサーバーOSはRocky Linux 8、WebサーバーはNginxを使用しています。
このサーバーでは、HTTP/3の対応として、大きく以下の3つが必要でした。
- ファイアウォールでUDP/443ポートをアクセス許可
- Nginxのアップデート
- 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
HTTP/3の動作確認
Webブラウザで、ページが正しく表示されることを確認します。
また、ブラウザのDeveloperToolsなどで、通信プロトコルが HTTP/3 となっていることを確認します。
Chrome DeveloperToolsでは、以下のように Protocols 列で h3 と表示されます。
また、HTTP/3 Checkサイトで確認するのもよいでしょう。
https://http3check.net/
当サイトはご覧のとおりシンプルなつくりですので(笑)、残念ながら「体感としてページ表示が速くなった」ということはありません。
HTTP/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のままとしています。
このように、思わぬ箇所で不具合が発生するケースもありそうなので、トップページだけではなく、認証、更新、ページ遷移など、しっかり動作確認されることをおすすめします。
おわりに
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