概要
「Welcome to the demo site for nginx-quic」を参考にHTTP/3に対応したNginxの構築を行います。
※既に同じような記事がたくさん書かれていますが、微妙に構築手順に差異があったので自分用としてまとめてみました。
動作環境
- ホストOS: macOS Monterey 12.0.1(Intel Core i7)
- Vagrant: 2.2.19
- VirtualBox: 6.1.30
- ゲストOS: Ubuntu 20.04 LTS
- HTTP/3対応のwebサーバー: Nginx 1.21.5
- HTTP/3対応のwebクライアント: curl 7.82.0-DEV
仮想環境の構築
「Ubuntu 20.04 LTS」の Vagrantfile を作成します。
$ vagrant init ubuntu/focal64
オリジナルの Vagrantfile をコピーします。
$ cp Vagrantfile Vagrantfile.orig
Vagrantfile の最下行に以下を追記します。(メモリのサイズに関しては環境に応じて適宜設定してください)
% diff Vagrantfile Vagrantfile.orig
70,72d69
< config.vm.provider "virtualbox" do |vb|
< vb.memory = "8192"
< end
仮想環境を起動します。
$ vagrant up
仮想環境にSSHログインします。
$ vagrant ssh
各パッケージを更新します。
$ sudo apt -y update
$ sudo apt -y upgrade
BoringSSLをインストール
「Experimental QUIC support for nginx」の「2. Installing」を参照すると、「You will need a BoringSSL library that provides QUIC support」とあるので、まずは BoringSSL をインストールします。
BoringSSL は「BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.」とのこと。
「Building BoringSSL」のBuild Prerequisitesを参照すると以下のような記述があるため、必要なパッケージをそれぞれインストールします。
CMake 3.5 or later is required.
CMake が必要。 → cmake をインストールします。
Building with Ninja instead of Make is recommended
ビルド時は Make よりも Ninja がオススメ。 → ninja-build をインストールします。(あとの手順で make も必要なので一緒にインストールします)
C and C++ compilers with C++11 support are required.
C と C++ のコンパイラが必要。 → gcc と g++ をインストールします。
The most recent stable version of Go is required.
Goの安定版が必要。 → golang をインストールします。
the tests have an optional libunwind dependency
テストが libunwind に依存。 → libunwind-dev をインストールします。
また、 BoringSSL のページの「Clone this repo」を見ると、Gitでリポジトリを管理しているようなので、 git も一緒にインストールします。
$ sudo apt -y install \
cmake \
ninja-build \
make \
gcc \
g++ \
golang \
libunwind-dev \
git
「Building BoringSSL」のBuildingの手順のとおりにインストールを行います。
$ cd ~
$ git clone https://boringssl.googlesource.com/boringssl
$ cd boringssl
$ mkdir build && cd $_
$ cmake -GNinja ..
$ sudo ninja
インストール後にテストを行う場合は「Running Tests」を参考に行います。
$ cd ..
$ sudo ninja -C build run_tests
Nginxをインストール
「Experimental QUIC support for nginx」の「2. Installing」を参照すると hg コマンドを利用しているので、 mercurial をインストールします。
$ sudo apt -y install mercurial
「2. Installing」の手順に沿ってインストールを進めると、以下のようなエラーが発生する場合があります。
./auto/configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
./auto/configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib=<path> option.
インストールを進める上で「PCRE library」と「zlib library」が必要とのことなので、事前に libpcre3-dev と zlib1g-dev をインストールしておきます。
$ sudo apt -y install libpcre3-dev zlib1g-dev
「Experimental QUIC support for nginx」の手順のとおりにインストールを行います。
$ cd ~
$ hg clone -b quic https://hg.nginx.org/nginx-quic
$ cd nginx-quic
$ ./auto/configure \
--with-debug \
--with-http_v3_module \
--with-cc-opt="-I../boringssl/include" \
--with-ld-opt="-L../boringssl/build/ssl \
-L../boringssl/build/crypto"
$ make
$ sudo make install
nginx コマンドの「-V」オプションでインストール時のオプション等を確認します。
$ /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.21.5
built by gcc 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
built with OpenSSL 1.1.1 (compatible; BoringSSL) (running with BoringSSL)
TLS SNI support enabled
configure arguments: --with-debug --with-http_v3_module --with-cc-opt=-I../boringssl/include --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto'
SSL証明書の作成
Homebrew を利用するため https://brew.sh/ の手順に従いインストールします。
$ cd ~
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
・
・
==> Next steps:
- Run these two commands in your terminal to add Homebrew to your PATH:
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/vagrant/.profile
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
- Install Homebrew's dependencies if you have sudo access:
sudo apt-get install build-essential
For more information, see:
https://docs.brew.sh/Homebrew-on-Linux
- We recommend that you install GCC:
brew install gcc
- Run brew help to get started
- Further documentation:
https://docs.brew.sh
インストールの最後に表示されている「Next steps」の指示通りコマンドを実行します。
$ echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /home/vagrant/.profile
$ eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
brew コマンドが実行できるか確認します。
$ brew -v
Homebrew 3.3.10
Homebrew/homebrew-core (git revision 9188a0a50d5; last commit 2022-01-17)
mkcert をインストールします。
$ brew install mkcert
自己認証局を設定します。
$ mkcert -install
Created a new local CA 💥
The local CA is now installed in the system trust store! ⚡️
mkcert へのパスが通っていない root ユーザーで実行するため事前にフルパスを確認します。
$ which mkcert
/home/linuxbrew/.linuxbrew/bin/mkcert
SSL証明書を作成します。
$ sudo mkdir /usr/local/nginx/conf/certs && cd $_
$ sudo /home/linuxbrew/.linuxbrew/bin/mkcert localhost
Created a new certificate valid for the following names 📜
- "localhost"
The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅
It will expire on 17 April 2024 🗓
SSL証明書がカレントディレクトリに作成されていることを確認します。
$ ls -l localhost*
-rw------- 1 root root 1704 Jan 17 03:46 localhost-key.pem
-rw-r--r-- 1 root root 1464 Jan 17 03:46 localhost.pem
Nginxの設定ファイルの準備
Experimental QUIC support for nginxの「3. Configuration」を参考に nginx.conf を修正します。
オリジナルの nginx.conf をコピーします。
$ sudo cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.orig
nginx.conf に以下を追記します。
$ diff /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.orig
117,137d116
< log_format quic '$remote_addr - $remote_user [$time_local] '
< '"$request" $status $body_bytes_sent '
< '"$http_referer" "$http_user_agent" "$http3"';
<
< access_log logs/access.log quic;
<
< server {
< # for better compatibility it's recommended
< # to use the same port for quic and https
< listen 8443 http3 reuseport;
< listen 8443 ssl;
<
< ssl_certificate certs/localhost.pem;
< ssl_certificate_key certs/localhost-key.pem;
< ssl_protocols TLSv1.3;
<
< location / {
< # required for browsers to direct them into quic port
< add_header Alt-Svc 'h3=":8443"; ma=86400';
< }
< }
nginx.conf のチェックを行います。
$ sudo /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
systemd経由でNginxを起動するため、「NGINX systemd service file」を参考に制御用のファイルを作成します。
$ cat /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Nginxの起動
以下のコマンドでNginxを起動します。
$ sudo systemctl start nginx.service
ポート8443がLISTEN状態であることを確認します。
$ ss -lnt |grep ':8443'
LISTEN 0 511 0.0.0.0:8443 0.0.0.0:*
標準でインストールされている curl コマンドでレスポンスが返ってくるか確認します。
$ curl -I https://localhost:8443
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Mon, 17 Jan 2022 04:25:35 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Mon, 17 Jan 2022 03:04:29 GMT
Connection: keep-alive
ETag: "61e4dcbd-267"
Alt-Svc: h3=":8443"; ma=86400
Accept-Ranges: bytes
HTTP/3に対応した curl コマンドをインストール
curl のリポジトリの「HTTP3 (and QUIC)」を参考にHTTP/3に対応した curl コマンドのインストールを行います。
今回は「quiche version」の手順に従ってインストールを行います。
必要なパッケージをインストールします。
$ sudo apt -y install cargo autoconf libtool
quiche と BoringSSL のインストールを行います。
$ cd ~
$ git clone --recursive https://github.com/cloudflare/quiche
$ cd quiche
$ cargo build --package quiche --release --features ffi,pkg-config-meta,qlog
$ mkdir quiche/deps/boringssl/src/lib
$ ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) quiche/deps/boringssl/src/lib/
curl のインストールを行います。(configure実行時に「HTTP3 enabled but marked EXPERIMENTAL. Use with caution!」というメッセージが表示されますので、あくまで検証用途としての利用に留めておいた方がよさそうですね)
$ cd ..
$ git clone https://github.com/curl/curl
$ cd curl
$ autoreconf -fi
$ ./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" --with-openssl=$PWD/../quiche/quiche/deps/boringssl/src --with-quiche=$PWD/../quiche/target/release
・
・
WARNING: HTTP3 enabled but marked EXPERIMENTAL. Use with caution!
$ make
$ sudo make install
src ディレクトリ配下にHTTP/3対応の curl コマンドがインストールされたことを確認します。
$ ./src/curl --version
curl 7.82.0-DEV (x86_64-pc-linux-gnu) libcurl/7.82.0-DEV BoringSSL zlib/1.2.11 quiche/0.10.0
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTP3 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL UnixSockets
HTTP/3対応の curl コマンドでHTTPリクエストを実行
先程インストールしたHTTP/3に対応した curl コマンドに「--http3」オプションを付与してリクエストを行うと、「HTTP/3 200」という結果が返ってくることが確認できました。
$ ./src/curl -I https://localhost:8443 --http3
HTTP/3 200
server: nginx/1.21.5
date: Mon, 17 Jan 2022 05:08:36 GMT
content-type: text/html
content-length: 615
last-modified: Mon, 17 Jan 2022 03:04:29 GMT
etag: "61e4dcbd-267"
alt-svc: h3=":8443"; ma=86400
accept-ranges: bytes
参考URL
- Our Roadmap for QUIC and HTTP/3 Support in NGINX
- QUICおよびHTTP/3対応のNGINXプレリリース版のご紹介 (英語版)
- HTTP/3とQUICについてざっくり解説
- HTTP/3が出るらしいという話を雑に書く
- HTTP/3とQUICはなぜ必要になり、どのように標準化されてきたのか? 現代のプロトコル設計とインターネットの課題
- HTTP/3の基盤となる「QUICプロトコル」の標準化プロセスが完了、IETFの「RFC 9000」として
- GoogleによるOpenSSLのfork、BoringSSLを試す。
- 【QUIC対応】HTTP/3対応版nginxを使えるようにBoringSSLのビルドからやってみた
- NginxのHTTP/3を試す (2020年6月)
- nginx-quic をビルドしてみた
- HTTP/3 対応の nginx を作る
- QUIC及びHTTP/3対応のNGINXサーバーを構築
- Experiment with HTTP/3 using NGINX and quiche
- How to use HTTPS for local development
- 開発環境をhttps化するmkcertの仕組み
- WEB+DB PRESS Vol.123