OpenSSL 1.0.2 以降をインストールしてもALPNに対応できないときの対処法

ALPNに対応しているか確認

自分のサイトでALPNが有効かどうかは以下の3つの方法で確認できます。

  1. Chrome拡張機能HTTP/2 and SPDY indicator」を使用する
  2. WebサービスHTTP/2 Test」を使用する
  3. OpenSSLコマンドを実行する

1つめ

拡張機能Chromeにインストールするだけで準備OKです。ALPNが有効であり、かつHTTP/2が有効である場合はこの拡張機能の稲妻アイコンが青くなります(非対応の場合は灰色です)

2つめ

WebサイトにアクセスしてALPN対応かどうか確認したいサイトのURLを入力して「Test」ボタンを押します。"ALPN supported" と出ればALPNに対応していることがわかります。

3つめ

opensslコマンドが使用できるマシンで以下のコマンドを実行します。

$ echo | openssl s_client -alpn h2 -connect example.com:443

example.comの箇所を確認したいURLに置き換えます。コマンドを実行すると色々な情報が出てきますが、ALPNに対応していれば

ALPN protocol: h2

と表示され、対応していなければ

No ALPN negotiated

と表示されます。

参考: NginxでHTTP/2(ALPN対応)

問題

OpenSSLはALPNをサポートしていますが、サポートしているバージョンは OpenSSL 1.0.2 以降です。なので、OpenSSL 1.0.1 などではALPNはサポートされていません。

ところが、OpenSSLのバージョンがALPNに対応していても、なぜかALPN非対応と表示されてしまう問題に直面しました。Webサーバ(Nginx)を再起動してもダメでした。

解決策

ぼくの場合は以下の2つが原因でした。

  1. NginxがALPNに対応したOpenSSLを使用していなかった
  2. サーバ自体を再起動する必要がある

1つめ

NginxやOpenSSLをyumやaptなどのパッケージマネージャで更新した場合は問題ないのですが、自分の場合は、NginxもOpenSSLも、ソースからダウンロードしてビルドしていたので、NginxがビルドしたOpenSSLを参照してくれていなかったのが原因でした。

ソースからビルドしたNginxで、同じくソースからビルドしたOpenSSLを使用するためには、Nginxにインストールでオプションをつけて、もう一度ビルドし直す必要があります。Nginxのソースがあるディレクトリに移動して、以下のコマンドを実行します。

$ ./configure --with-http_ssl_module --with-http_v2_module --with-openssl=ソースからダウンロードしたOpenSSLのディレクトリのパス

OpenSSLは公式サイトからtarball(.tar.gz)をダウンロードして、圧縮ファイルを展開します。その展開したディレクトリをパスとして指定します。Nginxをソースからビルドする方法については以下の記事を参考にしてください。

Nginxでレスポンスヘッダの一部を隠蔽する方法

これでインストールすると、指定したOpenSSLのバージョンを使ってNginxをビルドできます。それを確認するには以下のコマンドを実行します。

$ nginx -V

built with OpenSSL x.x.x DD MM YYYYのように、自分がダウンロードしてきたOpenSSLのバージョン(1.0.2以降)が表示されていればOKです。Apacheの場合はまた違うと思いますので、各自で調べてください。

ビルドが成功したら、Nginxを再起動してください。

$ sudo nginx -s reload

2つめ

これは非常に単純な話なのですが、Nginxを再起動しただけでは、OpenSSLのバージョンを変更してもそれが反映されないみたいです。おそらくOpenSSLを新しいバージョンにしたほうに反映させるコマンドがあるはずですが、自分はそれがわからなかったので、最終手段としてサーバそのものを再起動してしまいました。サーバを再起動するので、再起動後に自動起動するように設定していないデーモンプロセスを再び起動させる手間があってめんどうくさいですが、これが一番確実かと思われます。

サーバを再起動して、もう一度、3つのうちのいづれかの方法でALPN対応か確認するとちゃんと対応していると表示されました!

最新版のOpenSSLのインストール方法についてはこちらをどうぞ OpenSSLをソースからビルドしてNginxで使用する