1月 092020
 

2020 年の 正月に ports を csv update したら Firefox72 が降って来ていたので、そのまま FreeBSD/amd64 12.1-RELEASE にインストール。
しかし、ハタと考えてみた。『Firefox って 72 から HTTP/3 をサポートしたんじゃなかったけっ?』
果たして about:config で確認してみると

network.http.http3.enabled

と、いうのがあるではないかっ!! これをすかさず true にして google などを確認してみる。

HTTP/3 というのは、チョー簡単に言うと UDP で SSL 通信を行うものであります。詳細についてはウェブで情報を探してください;-P。
ファイアーウォールなどで UDP の 443 ポートなんてのは中々開いているものではないので、自宅なり、オフィスなりのファイアーウォールをまず先に確認してみましょう。

 
しかし、自分でも UDP:443 で通信するサーバを構築してみたい。色々探してみると apache24 はまだ、未対応ですが、 nginx は対応パッチが出ているようです。

まずは以下の URL にアクセス。

https://blog.cloudflare.com/experiment-with-http-3-using-nginx-and-quiche/

 
ここに記載されている git からパッチを取ってきて nginx のソースにパッチを当てて make しても良いんだけど、configure のオプションがややこすぃー。せっかく FreeBSD が手元にあるので ports の nginx に quiche パッチを適用してサーバ環境を構築してみましょう。

と、いうのが今回の趣旨です。ひと足お先に HTTP/3 を体験してみましょう。

このブログでは以前に apache24 で HTTP/2+TLSv1.3 対応にするエントリを書いていますが、今回は nginx のエントリになります。

 
1). ports の準備
以下に手順を書いてみます。

# cd /usr/ports/www/
# cp -pr nginx nginx-http3
# cd nginx-http3/
# git clone --recursive https://github.com/cloudflare/quiche
# make patch

 
原本となる /usr/ports/www/nginx/ は一応残しておいて nginx-http3/ というディレクトリで作業を始めます。
git から quiche を一式持ってきて、ports 的には make patch まで走らせます。make patch 時に make config が走ると思いますがお好みの設定で、絶対に忘れてはいけないオプションが HTTP_SSL と HTTPV2 です。 default で [X] になっていると思うんですけどね。

 
2). パッチ適用

# cd work/nginx-1.16.1/
# patch -p01 < ../../quiche/extras/nginx/nginx-1.16.patch
# cd ../..

 
nginx-1.16 用の quiche パッチなので、最新の ports ツリーであれば容易に適用できます。

 
3). ports の Makefile の編集
www/nginx-http3/Makefile を編集します。上記 URL では configure オプションが記載されていますが、それを FreeBSD の ports に書いて上げます。

diff -ur Makefile.orig Makefile
--- Makefile.orig       2020-01-03 12:00:17.947717000 +0900
+++ Makefile    2020-01-03 12:01:29.885305000 +0900
@@ -53,6 +53,9 @@
 
 HAS_CONFIGURE= yes
 CONFIGURE_ARGS+=--prefix=${ETCDIR} \
+               --with-http_v3_module \
+               --with-openssl=/usr/ports/www/nginx-http3/quiche/deps/boringssl \
+               --with-quiche=/usr/ports/www/nginx-http3/quiche \
                --with-cc-opt="-I ${LOCALBASE}/include" \
                --with-ld-opt="-L ${LOCALBASE}/lib" \
                --conf-path=${ETCDIR}/nginx.conf \

 
さーっ!! 準備ができたのでいよいよ make だぁっ!! などと思っては行けません。 quiche 側のソースコードのコンパイルには rust の cargo build を実行するので、なんとっ!! ここへ来て、 rust をインストール必要があります。
Firefox を自前でコンパイルする人は既に rust はインストール済みだと思われるため簡単ですが、持っていない人は /usr/ports/lang/rust/ を make install しましょう。速いマシンでも 30 分くらいかかると思いますけど。

 
rust のインストールが終わったらいよいよ nginx を make install します。

 
以上で HTTP/3 対応 nginx のインストールが完了しました。めでたしめでたし。

 
4). nginx.conf の設定
nginx.conf の設定は抜粋のみです。

user  www;
worker_processes  4;

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  16;
}

http {

    autoindex off;

    server {
        listen [::]:443 quic reuseport;
        listen [::]:443 ssl  http2;
        listen      443 quic reuseport;
        listen      443 ssl  http2;

        server_name         nx.icmpv6.org;

        access_log  /var/log/nginx/access_nx_icmpv6_org.log;

        location / {
            root   /usr/local/www/nginx;
            index  index.html index.shtml index.php;
            allow  all;
        }

        ssl_certificate     /usr/local/etc/letsencrypt/live/nx.icmpv6.org/cert_chain.pem;
        ssl_certificate_key /usr/local/etc/letsencrypt/live/nx.icmpv6.org/privkey.pem;

        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_session_cache   shared:SSL:1m;
        ssl_session_timeout 5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        add_header alt-svc 'h3-23=":443"; ma=86400';

        http3_max_concurrent_streams 128;
        http3_max_requests           1000;
        http3_max_header_size        16k;
    }
}

 
listen は計 4 行ありますが、HTTP/3 で接続する場合には 443 quic reuseport の行が利用されます。 HTTP/3 に対応していないブラウザでは HTTP/2 で待ち受けるので、その設定は 443 ssl http2 になります。

そして、IPv6/IPv4 のデアルスタクです。

HTTP/2 も HTTP/3 も SSL が必須なので証明書を準備しましょう。 SSL 関連の設定もお忘れなく。

 
5). 実際に起動してみる
まず、何はなくとも以下のコマンドを叩いて確認。

$ netstat -an | grep 443
tcp4       0      0 *.443                  *.*                    LISTEN     
tcp6       0      0 *.443                  *.*                    LISTEN     
udp4       0      0 *.443                  *.*                    
udp4       0      0 *.443                  *.*                    
udp6       0      0 *.443                  *.*                    
udp6       0      0 *.443                  *.*
$
# tcpdump -i em0 udp port 443

 
うぉー。udp4,6 で port:443が開いているっ!!
tcpdump を起動して、UDP の port:443 でパケットが流れているか、確認ができます。
また、nginx のアクセスログで "GET / HTTP/2.0" は TCP Port:443 の接続になります。 "GET / HTTP/3" が UDP の Port:443 の接続になります。
上記の nginx の設定ではもう HTTP/2 か HTTP/3 の接続になりますな。高級なブラウザの場合は HTTP/2 か HTTP/3で、 w3m でアクセスするとようやっと "GET / HTTP/1.0" でのアクセスになります。

 
あとは nginx の root パスにドカドカコンテンツを置いていけば良いと思われます。

しかし、 netstat -an で UDP port:443 を確認して待受状態になっているにも関わらず接続できない場合があります。
サーバ側で tcpdump で確認してみると、クライアント側からアクセスがあるだけで、サーバ側からの応答がない場合が・・。しかし、とあるタイミングでは接続できるので・・。今の所 nginx を再起動してみたりと、いう運用ですかねぇ。

あと、Firefox72 は HTTP/3 で接続できなかった場合 HTTP/2 や HTTP/1.1 にフェイルオーバーしません。 HTTP/3 の応答が無くともずっと待っている状態になります。 about:config の HTTP/3 のタイムアウト設定も見当たらないし・・。

 
と、いうことで、今から遊ぶには十分に楽しい HTTP/3 です。FreeBSD では ports を利用すると Firefox72 は使えるわ、 nginx は ports にパッチを当てるだけで configure オプションに悩まなくて済むわ。比較的容易に、そして十分に楽しめること間違いなしです。

ここいらで UDP の世界にどっぷりとハマってみるのも良いのではないでしょうか;-)。