自社WebサイトをHTTP/2対応しました。

この「稲葉サーバーデザインWebサイト」、先日の完全HTTPS化に続き、HTTP/2化しました。

isdNginxのアップデートと設定変更

Webサーバーの構成はCentOS 7 + Nginxで、Nginxを使用したHTTP/2対応については次の記事がとても参考になりました。

・NginxによるHTTP/2 事始め
http://qiita.com/jpshadowapps/items/3da47ecaa8fbfc0c01ea

Nginxはバージョン1.9.5以降でHTTP/2をサポートしているとのことです。
CentOS向けNginxリポジトリの最新バージョンは1.8.1ですので、最新安定版のソースからをビルド、インストールするつもりでしたが、安定版(stable)ではなくメインライン(mainline)のバージョンを取得するようリポジトリのbaseurlを変更すれば、1.9.15をインストールできることがわかりました。

(参考)
・nginxでHTTP/2ことはじめ
https://saku.io/introduce-http2-with-nginx/

 # vi  /etc/yum.repos.d/nginx.repo

--
#baseurl=http://nginx.org/packages/centos/7/$basearch/
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
--

 # yum clean all

 # yum info nginx

インストール済みパッケージ
名前                : nginx
アーキテクチャー    : x86_64
エポック            : 1
バージョン          : 1.8.1
リリース            : 1.el7.ngx
容量                : 897 k
リポジトリー        : installed
提供元リポジトリー  : nginx
要約                : High performance web server
URL                 : http://nginx.org/
ライセンス          : 2-clause BSD-like license
説明                : nginx [engine x] is an HTTP and reverse proxy server, as
                    : well as a mail proxy server.

利用可能なパッケージ
名前                : nginx
アーキテクチャー    : x86_64
エポック            : 1
バージョン          : 1.9.15
リリース            : 1.el7.ngx
容量                : 640 k
リポジトリー        : nginx/x86_64
要約                : High performance web server
URL                 : http://nginx.org/
ライセンス          : 2-clause BSD-like license
説明                : nginx [engine x] is an HTTP and reverse proxy server, as
                    : well as a mail proxy server.

 # yum update nginx

...
更新:
  nginx.x86_64 1:1.9.15-1.el7.ngx
...

 

これで、Nginxが、1.8.1からHTTP/2に対応した1.9.15にアップデートされました。
続いて、Configで、HTTP2に対応させます。

listenディレクティブに http2 を追記します。
また参考記事によれば、HTTP/2で必須となる暗号スイート TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 を優先するよう、ssl_ciphersディレクティブの先頭に AESGCM:HIGH を記述するのがポイントとのことです。

 # vi /etc/nginx/conf.d/vhost_ssl_inaba-serverdesign.jp.conf

-- SSLまわりのみ抜粋
server {
    listen      443 ssl http2;

    server_name inaba-serverdesign.jp;

    ssl on;
    ssl_certificate      /etc/letsencrypt/live/inaba-serverdesign.jp/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/inaba-serverdesign.jp/privkey.pem;

    ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers          AESGCM:HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers   on;

    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;

    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    add_header Strict-Transport-Security max-age=15768000;
...
}

 # nginx -t
 # systemctl restart nginx

 

これで、HTTP/2対応は完了です。

アクセスログを見ると、HTTPリクエストの最後のHTTPプロトコルバージョンが ‘HTTP/2.0’ となっているアクセスがちらほら出てきました。

xxx.xxx.xxx.xxx - - [06/May/2016:17:03:48 +0900] "GET /blog/20151212/s3cmd_awscli_s3_idcf.html HTTP/2.0" 200 13381 "https://www.google.co.jp" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"

 

Google Chromeの拡張機能HTTP/2 and SPDY indicatorをインストールしてアクセスしてみると、ちゃんとHTTP/2プロトコルでの通信を意味する青い稲妻が表示されました。
(画像はクリックすると大きく表示されます。)

http2_indicator
 

isdHTTP/1.1とHTTP/2の比較

Google Chromeのディベロッパーツールで、トップページにアクセスしたときの、HTTP/1.1のときとHTTP/2にしてからの解析結果を比べてみます。

HTTP/1.1

http11
 

HTTP/2

http2
 

HTTP/2のほうは、オレンジ色のInitial Connection(初期接続確立までの時間)や紫色のSSL(SSLハンドシェイクに要した時間)が出てくる回数が1回だけで、1つの接続を使いまわしてリクエストを出していることがわかります。
(font-awesome.min.cssは外部サイトからのダウンロードです。)

このWebサイトはダウンロードするファイル数の少ないシンプルな構成にしているので、一番下に表示される「Load」の秒数(合計のダウンロード時間)はほとんど変わりませんが、ファイル数の多いページではレスポンスタイムの向上が期待できるでしょう。
また、ユーザーの1ページアクセスごとの接続数が減ることから、サーバーの負荷軽減も期待できますね。

isdなぜかHTTP/2で通信できない問題

余談になりますが、サーバー側でHTTP/2に対応した当初、僕のWindows PCからは、最新版のGoogle ChromeでもFirefoxでも、HTTP/2ではなくてHTTP/1.1通信となってしまう現象が発生しました。

  • FacebookやTwitterへのアクセスではHTTP/2となる。(HTTP/2 and SPDY indicatorで青い稲妻)
  • サーバー側のアクセスログを見ると、他のユーザーからはHTTP/2の通信がある。

という状況で、うまく切り分けできず原因がわかりませんでした。

翌日になって、SSLサーバー証明書の発行元が ‘ESET SSL Filter CA’ となっているのを見て、アンチウイルスソフトの「SSL/TLSプロトコルフィルタリング機能」が原因だとわかりました。

僕はESET NODアンチウイルスが気に入っていてずっと使っているのですが、最近バージョンを7から9にアップグレードしたところ、9では「SSL/TLSプロトコルフィルタリング機能」がデフォルトで有効となっていたのでした。
「SSL/TLSプロトコルフィルタリング機能」を有効にすると、WebブラウザとサーバーのHTTPS通信の間にESETクライアントが入って、たぶん、

 ESETクライアントがHTTPSリクエスト
  →レスポンスを復号して検査
  →問題なければESETのサーバー証明書で暗号化してWebブラウザに渡す

という動作をしているのでしょうか。
それで、ESETクライアントがHTTP/2に対応していないからHTTP/1.1となってしまう?

FacebookやTwitterへのアクセス時は、SSLサーバー証明書の発行元が ‘ESET SSL Filter CA’ ではなく、FacebookやTwitterとなっているので、これらのアクセス時にはSSL/TLSプロトコルフィルタリングを行っていないようなのも不思議ですが。

(参考)
・ESET Smart Security 9 が出た
https://bucci.bp7.org/archives/32555

とにかく、今回のHTTP/2通信に限らず、「SSL/TLSプロトコルフィルタリング機能」を有効にすると、SSLサーバー証明書の正しい発行元情報を確認できなくなるので、僕は無効にしました。

※SSLサーバー証明書の発行元情報で正当性を判断しにくいときは有用な機能だと思います。

これで、僕のWindows PC環境からも、無事「稲葉サーバーデザインWebサイトにHTTP/2通信できるようになりました。
 

isdGoogle ChromeでHTTP/2で通信できない問題

(このセクションは、2017.1.31に追記しました。)
その後、いつの間にかGoogle Chromeでは、HTTP/2ではなくHTTP/1.1での通信となってしまいました。
これは、2016年5月ごろリリースされたGoogle Chrome51以降では、HTTPS通信の際のTLSプロトコルネゴシエーション時にALPNという接続方式に対応していないとHTTP/2で通信できない仕様となってしまったからだそうです。

(参考)
・nginxをHTTP/2対応にする方法(Chrome 51以降でも有効にする)
http://qiita.com/bj1024/items/3a4029f7ca2383d7a641
など

現在のCentOS 7サーバー環境でALPNに対応するには、openssl-1.0.2とNginxのソースをダウンロードして、Nginxをソースビルドしなければならないとのこと。
Nginxのような基本的なソフトウェアをソースビルド(SRPMビルド)して運用するのは好みではないですし、そこまでHTTP/2にこだわりがあるわけではないので、残念ですが、今回はGoogle ChromeのHTTP/2対応はあきらめました。

(関連記事)
・自社WordPressサイトを完全HTTPS化しました。
https://inaba-serverdesign.jp/blog/20160502/move_wordperss_website_https.html
 

Follow me!