HTTP/2 は「WEBの高速化、通信量の削減、安全な接続」を目的とした、WEB通信プロトコルの最新バージョンです。2015年2月17日に、IETFの運営グループにより正式な仕様として承認されました。これまで長い間 HTTP/1.1 が使われていましたが、16年ぶりのバージョンアップになります。そこで今回は、HTTP/2 の実装として有名な Nghttp2 の nghttpd を使って、HTTP/2 WEBサーバを設定してみました。
(更新)2017年5月14日 各種インストール手順を最新版に更新しました。
HTTP/2 の特徴
HTTP/2 には以下の特徴があります。
バイナリフレームの採用
ストリームによる多重化
ヘッダー圧縮
サーバープッシュ
ストリームの優先度
HTTP/2 入門 - Yahoo! JAPAN Tech Blog より引用
HTTP/1.1 では、同時に処理できるリクエストは4〜6程度でしたが、HTTP/2では「ストリームによる多重化」により同時に100以上のリクエストを処理できるそうです。
HTTP/2 の普及状況
HTTP/2 に対応しているWEBブラウザ
Firefox、Chrom、IEなど、ほとんどWEBブラウザの最新バージョンでは、HTTP/2 に対応しています。http://caniuse.com/#search=HTTP%2F2(2015年4月14日現在)
また、各WEBブラウザは、HTTP/2 接続にはTLS(SSL)暗号化通信を必須としていますので、HTTP/2 のWEBサーバには、SSLサーバ証明書が必要になります。
HTTP/2 を使っている主なWEBサイト
WEBサイトで HTTP/2 が使われているかを確認するには、Firefox用の機能拡張「HTTP/2 Indicator 」が便利です。インストールすると、HTTP/2 が使われている場合は、アドレスバーの右側に、青い稲妻マークが表示されます。
この青い稲妻を頼りに、HTTP/2 の対応状況を調べてみると、Google、Twitter、Facebook(SPDY3.1) など、膨大な通信量があるWEBサイトで、導入が進んでいるようです。特にGoogleについては、HTTP/2 の元となった SPDY(スピーディ)を開発していたこともあって、ほとんどのサービスで、HTTP/2 が使われています。
Nghttp2 について
HTTP/2 サーバの実装は、数多く公開されていますが、その中でも Nghttp2 は、HTTP/2 プロトコルの実装の最有力とされているようです。tatsuhiro-t さんという日本の方が、開発されています。
Nghttp2 には、HTTP/2 対応のクライアント、サーバ、プロキシー、ベンチマーキングツールが含まれています。今回は、そのうち HTTP/2 サーバの「nghttpd」を使います。
開発ツールのインストール
サーバOSは CentOS7.3 (1611) です。CentOS6系は、ライブラリが古いため Nghttp2 のインストールが大変そうだったので、あきらめました。(^^;)
Nghttp2 はソースからコンパイルしますので、基本コマンドと開発ツールをインストールしておきましょう。
yum -y groupinstall development
OpenSSL 1.0.2 のインストール
ALPN(Application-Layer Protocol Negotiation)に対応している、OpenSSLバージョン1.0.2以上をインストールします。
Google Chrome バージョン51以降は、NPNが削除され、ALPNのみ対応となったようですので、WEBサーバでHTTP/2を使うには、事実上OpenSSL1.0.2以上が必須になります。
Transitioning from SPDY to HTTP/2 | Chromium Blog
まずはじめに OpenSSLのコンパイルに zlib を使うので、インストールしておきます。
OpenSSLのインストール(そこそこの時間がかかります)
wget https://www.openssl.org/source/openssl-1.0.2k.tar.gz
tar xvzf openssl-1.0.2k.tar.gz
cd openssl-1.0.2k/
./config --prefix=/usr/local/openssl-1.0.2k shared zlib
make depend
make
make test
make install
OpenSSL1.0.2 のライブラリにパスを通しておきます。
ldconfig
Nghttp2 (nghttpd) のインストール
Nghttp2 が必要とするライブラリのインストール
Nghttp2 のダウンロード
※頻繁にバージョンアップされているようです。ダウンロードの前に最新リリースを確認しましょう。
https://github.com/tatsuhiro-t/nghttp2/releases/latest
wget https://github.com/nghttp2/nghttp2/releases/download/v1.22.0/nghttp2-1.22.0.tar.gz
Nghttp2 のインストール。環境変数 OPENSSL_CFLAGS と OPENSSL_LIBS に先ほどインストールした、OpenSSL1.0.2 のディレクトリパスを指定してコンパイルします。また nghttpd をコンパイルするため「-enable-app」オプションを付けます。
cd nghttp2-1.22.0/
env OPENSSL_CFLAGS="-I/usr/local/openssl-1.0.2k/include" OPENSSL_LIBS="-L/usr/local/openssl-1.0.2k/lib -lssl -lcrypto" ./configure -enable-app
make
make install
/usr/local/bin/ 下に、「nghttpd」などの Nghttp2 のコマンド群がインストールされます。
SSLサーバ証明書(自己署名)の作成
前述しましたが、HTTP/2 を使ったWEBサーバには、SSLサーバ証明書が必須です。
・秘密鍵の作成
openssl genrsa 2048 > server.key
・CSR(証明書署名要求)の作成
openssl req -new -key server.key > server.csr ---下記を入力--------------------------- Country Name (2 letter code) [XX]:JP State or Province Name (full name) []:<空エンター> Locality Name (eg, city) [Default City]:<空エンター> Organization Name (eg, company) [Default Company Ltd]:<空エンター> Organizational Unit Name (eg, section) []:<空エンター> Common Name (eg, your name or your server's hostname) []:<ドメイン名> Email Address []:<空エンター> Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:<空エンター> An optional company name []:<空エンター> ------------------------------
・SSLサーバ証明書の作成(有効期限10年)
openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt
・秘密鍵とSSLサーバ証明書を適当な場所に移動
mv -i server.key /etc/pki/tls/private/ mv -i server.crt /etc/pki/tls/certs/
・セキュリティ確保のため nghttpd の実行ユーザ「nghttp2」を作成
useradd -d /run/nghttp2 -s /sbin/nologin nghttp2
・秘密鍵とSSLサーバ証明書のオーナーを「nghttp2」ユーザに変更
chown nghttp2:nghttp2 /etc/pki/tls/private/server.key chown nghttp2:nghttp2 /etc/pki/tls/certs/server.crt chmod 600 /etc/pki/tls/private/server.key chmod 600 /etc/pki/tls/certs/server.crt
・CSRを削除
rm server.csr
nghttpd の設定
・nghttpd の設定ファイルを作成します。
vi /etc/sysconfig/nghttpd
# worker スレッド数 WORKERS=1 # ドキュメントルート HTDOCS=/var/www/html # 待受ポート番号 PORT=8080 # サーバ秘密鍵 PRIVATE_KEY=/etc/pki/tls/private/server.key # サーバ証明書 CERT=/etc/pki/tls/certs/server.crt
・nghttpd 用の systemd設定ファイルを作成します。
vi /etc/systemd/system/nghttpd.service
[Unit] Description=nghttpd After=network.target [Service] Type=simple User=nghttp2 EnvironmentFile=-/etc/sysconfig/nghttpd ExecStart=/usr/local/bin/nghttpd -n $WORKERS -d $HTDOCS $PORT $PRIVATE_KEY $CERT [Install] WantedBy=multi-user.target
・上記設定を systemd に反映
systemctl daemon-reload
・systemd に反映されているか確認
systemctl list-unit-files | grep nghttpd ---(下記のような表示であればOKです)--------------------------- nghttpd.service disabled
・起動
systemctl start nghttpd
・自動起動設定
systemctl enable nghttpd
・「nghttp2」ユーザで、nghttpd が実行されているかを確認します。
ps aux | grep nghttpd ---(下記のような表示であればOKです)--------------------------- nghttp2 22977 0.0 0.1 52816 3532 ? Ss 5:54 0:00 /usr/local/bin/nghttpd -n 1 -d /var/www/html 8080 /etc/pki/tls/private/server.key /etc/pki/tls/certs/server.crt
・動作確認
「https://<サーバのアドレス>:8080」に、WEBブラウザで接続して確認します。ドキュメントルートに、なにもファイルが無ければ、以下の様に表示されます。しっかり HTTP/2 を示す青い稲妻マークが表示されていますね。
※サーバに接続できない場合は、firewallでブロックされているかもしれません。以下のコマンドで8080/tcp の接続を許可しておきましょう。
firewall-cmd --add-port=8080/tcp --permanent firewall-cmd --reload
終わりに
HTTP/2 の話からは外れますが、Nghttp2 関連コマンドの manマニュアルが、とても分かりやすく書いてあるので、英語が苦手な私でも、少しの時間でオプションの内容を理解することが出来ました。
Cのコードがあまり読めない私(^^;)としては、マニュアルが分かりやすい Nghttp2 が HTTP/2 WEBサーバの定番になって欲しいものです。
次回は、今回設定した HTTP/2 WEBサーバ と、HTTP/1.1のWEBサーバとの、スピート比較をしてみたいと思います。
コメント
Google Chrome 51以降のバージョンでは、NPNがサポートされなくなったこと(https://ma.ttias.be/chrome-drops-npn-support-for-http2-alpn-only/ および https://osdn.jp/magazine/16/05/27/202000)を理由としてこの方法を変える必要がありそうです。
実際、私のホームページはCentOSのリポジトリからもってきたnginxを利用していましたが、opensslを起因としてhttp2通信ができなくなったので、ソースコードからコンパイルする方法に切り替えました。
CentOSのopensslが古いことが原因なので、1.0.2以降をソースコードからひっぱってきてコンパイルするか、libresslやboringsslなどのフォークプロジェクトを利用するのがよさそうです(私はlibresslに切り替えました)。
>匿名希望さん
ご情報ありがとうございます!
記事を修正いたしました。