サーバ設定

CentOS7上のNginxとChromeでh2(HTTP/2)通信をさせるためにNginxをビルドした

ホストが CentOS 7 で Nginx と Chrome で h2 通信できない理由

  1. 最近の Chrome (たぶん Chrome 51) は NPN が削除されて ALPN のみになった。NPN とか ALPN ってなんじゃらほってのはこのへん
  2. CentOS 7 の OpenSSL は 1.0.1e (+パッチ)
  3. OpenSSL の ALPN 対応は 1.0.2 から(!)

そんなわけでバージョンが足りてなくて Nginx で http2 を設定に書いていても、HTTP/1.1 over TLS で通信されてしまうので悲しい状態に。

ちなみに、今のところ 1.0.2 以上でリリース出してるサーバに使えそうな OS は Ubuntu くらい…。ちょっと先走りすぎなんじゃないの Google さん。

回避策としては、

  1. あきらめる
  2. OpenSSL を入れ替える
  3. OpenSSL か LibreSSL の強まったバージョンにリンクして Nginx をビルドする

とかそんな感じで、入れ替えるのは正直かなりしんどいので、3 の手段をとることにしたという話。

Nginx は configure するときに、--with-openssl=/path/to/openssl-src な感じで OpenSSL/LibreSSL ソースのパスを指定してやるとうまいことビルドして静的リンクしてくれるという情報をゲットしたので、これに従って(今後の手間が少なくなるように)いい感じにビルドスクリプトを書いておきましたというただそれだけの話。

ビルドのベースは Nginx の RPM レポジトリにおいてある SRPM パッケージなのできっとほぼ同じものができているはず。
(この SRPM を取得・展開して SPEC ファイルにパッチを当てて適当に展開した LibreSSL と一緒にビルドするというのが先のビルドスクリプトの内容)

それぞれのバージョンを変えるときは、Makefile のあたまのほうの

NGINX_VERSION := 1.11.6
LIBRESSL_VERSION := 2.5.0
RPM_RELEASE := 2

を変えるときっとうまくいくはず。(RPM_RELEASE は RPM パッケージのバージョン番号の hoge-1.0.0-42.x86_64.rpm42 のところ)
ビルドは Docker 使ってるので、Docker をいい感じに整備する必要あり。

build.sh は私が一発でビルドできるようにしたものなので、ほかの環境だとパスとかPGP鍵とかが合わなくて悲しいので普通に $ sudo make とかするといいと思います。

*.fetus.jp のうち Nginx を使ってるサイト(このブログは H2O なので違う)はこのバージョンで動いていて、ちゃんと動作しているように見えるのでたぶん大丈夫なんじゃなかろうかと。
ただし、追従にどれだけかかるかは謎なので私を信じて jp3cki レポジトリからとるか、自分でビルドするかなんかまあ考えてください。

※ちなみに、jp3cki というのは私のアマチュア無線のコールサイン(JP3CKI, JN4QYA)由来で、私のことです。

ビルドして配ってるやつ:

$ nginx -V
nginx version: nginx/1.11.6
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
built with LibreSSL 2.5.0
TLS SNI support enabled
configure arguments: (略)

$ ldd `which nginx`
        linux-vdso.so.1 =>  (0x00007fff97bf8000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f881cbf3000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f881c9d7000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f881c79f000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f881c53e000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f881c328000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f881bf65000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f881ce08000)
        libfreebl3.so => /lib64/libfreebl3.so (0x00007f881bd62000)

公式のRPM:

$ nginx -V
nginx version: nginx/1.11.6
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: (略)

$ ldd `which nginx`
        linux-vdso.so.1 =>  (0x00007fffa21ef000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f424ab64000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f424a948000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f424a710000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f424a4af000)
        libssl.so.10 => /lib64/libssl.so.10 (0x00007f424a242000)
        libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f4249e59000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f4249c43000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f4249881000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f424ad73000)
        libfreebl3.so => /lib64/libfreebl3.so (0x00007f424967d000)
        libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f4249431000)
        libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f424914c000)
        libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f4248f47000)
        libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f4248d15000)
        libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f4248b06000)
        libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f4248901000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f42486e7000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f42484c2000)
        liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f424829c000)

なんかライブラリがいろいろ違うのは、libssl あたりからのリンク分っぽい。