🔥

nginxでHTTP/3を使う方法 2023年5月版

2023/05/20に公開

ついさっき、ついにHTTP/3対応のブランチが本家のnginxにmergeされました。

https://github.com/nginx/nginx/commit/4b0266174814e6cf60a275321121dbaab084ee64

このまま何事もなければ次のMainline versionである1.25.0がリリースされたタイミングで使えるようになるはずです。

検索するとnginxでHTTP/3を使う方法を解説しているサイトがいくつかヒットしますが、実はmergeするちょっと前くらいから非互換な変更をいくつも入れていたので、そのままだと動かないはずです。なので簡単に使い方を解説しておきます。

なお分かっていると思いますが、こちらの記事は記事執筆時点(2023/05/20)の内容です。

OpenSSLの代わりを選ぶ

HTTP/3を使うには自分でbuildする必要があります。いずれpackageが配布されるだろうと思っている人がいるかもしれませんが、nginxのHTTP/3対応はBoringSSLのAPIで対応されています。OpenSSLはBoringSSLのAPIに対応していないどころか、まだHTTP/3に必要なAPIを実装していないので、OpenSSLとの組み合わせでは利用できません。

今後どうなるかは分かりませんが、とりあえず今のnginxの実装を使いたいならOpenSSLを利用することを辞めるしかないため、自分でbuildする前提で考えてください。

そしてなぜかmerge前にREADMEが消されてしまって読めなくなっているのですが、nginxでHTTP/3を利用するためにOpenSSLの代わりに利用する実装は以下の3つがあるので、まずどれかを選ぶ必要があります。

  • BoringSSL
    • GoogleのOpenSSLのForkでHTTP/3対応のデファクトスタンダードを作った
  • LibreSSL
    • セキュリティを重視するOpenSSLのForkで、BoringSSL QUIC APIをExperimental supportしている
  • QuicTLS
    • 当初はOpenSSLにHTTP/3対応コードを追加するために作業していたが、現在はmergeを断念している。OpenSSLのソースコードへの追従は随時行っており、node.jsのHTTP/3対応にも利用されるなど利用が広がっている

私は個人的に普段からLibreSSLを推しているので、今回はLibreSSLを利用します。ちなみに他の2つは配布されているtar.gzファイルが展開するとファイル名とディレクトリ名が食い違っているなど、微妙に扱いづらい部分があるので気をつけてください。

configureのOptionを変更する

この辺が少し変わっています。

おそらく今までの記事などだと./auto/configureを利用していると思いますが、これはリリースファイル生成時にmvしているので、1.25.0のリリースファイルの場合、今まで通り./configureで利用可能と思います。なのでここは今まで通りの作業で問題ないでしょう。

追加する必要があるオプションは--with-http_v3_moduleのみです。--with-stream_quic_moduleは現在削除されているので指定しないでください。

設定ファイルを変更する

以下のような設定を適切な場所に追加します。ちなみにHTTP/2はhttp2ですが、HTTP/3はquicを渡すので間違えないようにしてください(元々http3でしたが、現在は利用できません)。

listen 443 quic reuseport;

reuseportが必要です。また今回の対応とは別にnginxのlistenの仕様が変わっているので気をつけてください。個人的にはdefault_serverの設定でlisten 443 quic reuseport default_server;というようにしておいて、HTTP/3を有効にしたいドメインでlisten 443 quic;と設定するのがおすすめです。

https://twitter.com/catatsuy/status/1644614024838127617

ちなみにこれとは別にブラウザがHTTP/3を有効にするためにはAlt-Svcヘッダーが基本的に必要なので、以下のヘッダーも忘れずに追加します。

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

Alt-Svcヘッダー以外の手法としてHTTPSレコードがありますが、使えるDNSサービスが限られるのと、そもそもChromeでは有効にならず、Firefoxでも有効にするには現時点ではDNS over HTTPSを有効にする必要があります。

https://blog.jxck.io/entries/2022-02-05/http3.html

おまけ:nginx-buildの状況

nginxのbuildにnginx-buildを利用している人も多いと思います。

https://github.com/cubicdaiya/nginx-build

残念ながら、nginx-buildはOpenSSLとLibreSSLしか対応していません(ちなみにLibreSSL対応を追加したのは私です)。BoringSSLなどに対応するのは少し面倒(前述の通り、配布しているファイルが使いづらい状況のため)なので、今後対応するかは不明です。

ただnginx-buildは手元のファイルのチェックなどは特にしていないため、適当に手元のファイルを置き換えてしまえばbuild処理を実行することができます。まずOpenSSLなどでbuildした上で、OpenSSLの展開済みディレクトリをBoringSSLなどに置き換えることでbuild処理を実行することができます。

LibreSSLであれば-libresslオプションを渡すだけで利用できるため、個人的にはこちらのオプションの利用をお勧めしたいところです(このオプションを足したのは私自身であることに注意してください)。

最後に

これでHTTP/3ライフを楽しめる!と思った人もいると思いますが、そもそも以下のことを理解した上で利用した方が良いと思います。

  • HTTP/3はHTTP/2で発生しているTCPのHead of Line Blockingを防ぐために考案された仕組みであり、TCPの通信が安定しているネットワークでは効果は薄い
    • それどころか、TCPよりも最適化されてない可能性が高いUDPを利用する必要があるためCPU使用率などが上がり、むしろパフォーマンスが下がる可能性がある
    • よってTCPの通信が安定しているデータセンター内やデータセンター間の通信で利用されるものではない
  • HTTP/3を実装しているクライアントはブラウザにほぼ限られているため、CDNを挟んでいる場合は、CDNからの通信ではHTTP/3を利用しない
    • 前述の理由からそもそもデータセンター間通信で利用されるとは考えづらく、今後も実装されないと考えられる
    • つまりHTTP/3を有効にするメリットがあるのは前段にCDNなどを挟んでおらず、直接ユーザーと通信するサーバーを抱えている組織に限られる
    • 昨今はCDNを挟むのが一般的であるため、うれしい組織はほぼないと考えられる
    • ちなみにかなり面倒だが、自分でbuildすればcurlでHTTP/3を有効にすることは可能
      • curlのドキュメントではBoringSSLとQuicTLSを利用する方法しか解説されていませんが、LibreSSLも自分がやってみたら使えました

https://zenn.dev/catatsuy/scraps/3cf52a64a95c61

ということで適切にnginxでHTTP/3を使っていきましょう!よいHTTP/3ライフを!!

Discussion