LibreSSL と H2O で HTTP/2

[HTTP/2](https://http2.github.io/) を利用するためには TLS 通信ソフトウェアが必要となります。
この TLS 通信ソフトウェアとしても OpenSSL が使われていますが、LibreSSL を利用することもできます。
HTTP/2 での通信を、新しい HTTP サーバ H2O と LibreSSL の組み合わせで確認してみます。

---

# はじめに

## HTTP/2 と TLS の関係と制約

HTTP/2 と TLS通信の関係について確認しておきます。
HTTP/2 で通信を行うためには、Webサーバ側とブラウザ側の両方で HTTP/2 機能がサポートされている必要があります。また双方で実現されている HTTP/2 仕様が同じでなければなりません。

HTTP/2 自体は http と https の両方に対応するように仕様が策定されています。
どちらの場合も、HTTP/2 で通信するということを Webサーバ側とブラウザ側の間で取り決め(Negotiate)しなければなりません。

- http の場合は 'Upgrade: h2c' ヘッダを利用
- https の場合は TLS 拡張の ALPN を利用

ただし現在、主なブラウザは https の場合の ALPN による取り決め(Negotiate)の方しかサポートしていません。このため、ブラウザを相手にする Webサーバは、HTTP/2 対応するなら ALPN が必要ということになります。

ALPN は OpenSSL 1.0.2 でサポートされています。1.0.1 ではサポートされていません。LibreSSL は ALPN をサポートしています。

以上により、HTTP/2 サポートを OpenSSL を前提として提供する Webサーバは、OpenSSL なら 1.0.2 以降を使う必要があります。そしてその代替として LibreSSL も検討できるということになります。

## HTTP/2 の TLS 通信ソフトウェアに LibreSSL を使うメリット
HTTP/2 通信で新しい暗号スイートの ChaCha20-Poly1305 を使えるのが LibreSSL を選択する場合のメリットでしょう。

OpenSSL では現在開発中の 1.1.0 で ChaCha20-Poly1305 がサポートされますが、現行の 1.0.2 と 1.0.1 ではサポートされていません。
https://www.openssl.org/news/openssl-1.1.0-notes.html

## 環境
今回の確認は CentOS7 (x86_64) で行いました。

# HTTP/2 を H2O と LibreSSL で確認

[H2O](https://h2o.examp1e.net/) は HTTP/2 をサポートする新しい HTTP サーバです。
H2O は TLS 通信ソフトウェアとして OpenSSL と LibreSSL の両方が想定されています。
今回は最新の H2O を LibreSSL と組み合わせてビルドして、動作確認をしてみます。

## H2Oのインストール

以下の場所から最新の version 2.0.0 をダウンロードします。
https://github.com/h2o/h2o/archive/v2.0.0.tar.gz

H2O version 2.0.0 には misc/ の下に libressl-2.2.7.tar.gz が同梱されています。
今回はこれを使ってビルドを行います。
(misc/libressl.mk 内の `VERSION` を書き換えれば最新の LibreSSL も使えそうです。)

```shell-session
# tar xf v2.0.0.tar.gz
# cd h2o-2.0.0/
# cmake -DWITH_BUNDLED_SSL=on .
# make
# make install
```
以上で `/usr/local/` 配下に H2O がインストールされます。

## H2O の設定と起動

H2O は `/usr/local/share/doc/h2o/` 以下にドキュメントやサンプルがあります。
今回はこのサンプルを利用しつつ、以下の設定ファイルを作って簡単に HTTP/2 での接続確認をしました。

```js:/root/h2o.conf
hosts:
  "test.com":
    listen:
      port: 80
    listen:
      port: 443
      ssl:
        certificate-file: /usr/local/share/doc/h2o/examples/h2o/server.crt
        key-file:         /usr/local/share/doc/h2o/examples/h2o/server.key
    paths:
      "/":
        file.dir: /usr/local/share/doc/h2o/examples/doc_root

access-log: /var/log/h2o-access-log
error-log: /var/log/h2o-error-log
pid-file: /var/log/h2o-pid-file

```
設定は以上で完了です。
次に以下のコマンドで H2O を起動します。

```shell-session
# /usr/local/bin/h2o -m daemon -c /root/h2o.conf
```

## 動作確認

Chrome 51.0.2704.84 m (64-bit) で https にアクセスしてみると、"Welcome to H2O - an optimized HTTP server" の文字列を確認できました。
また以下のスクリーンショットのように、Protocol が `h2` と表示され HTTP/2 で通信されていることが分かります。
![http2_chrome.png](https://qiita-image-store.s3.amazonaws.com/0/103043/a50d32ec-1186-21ce-a34f-ae1a3e382acb.png)

`openssl s_client` コマンドで `-alpn h2` を指定することで ALPN が有効なことを確認することもできます。

```shell-session
# /usr/local/bin/openssl s_client -port 443 -cipher 'CHACHA20' -alpn h2
CONNECTED(00000003)
...
---
SSL handshake has read 1565 bytes and written 387 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-CHACHA20-POLY1305-OLD
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
ALPN protocol: h2
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-CHACHA20-POLY1305-OLD
...
```
"ALPN protocol" が `h2` になっていることが分かります。

# まとめ
HTTP/2 対応の Webサーバ構築のためには ALPN が必要です。
LibreSSL は ALPN をサポートしており、HTTP/2 を提供する Webサーバで TLS 通信ソフトウェアとして利用可能なことを確認しました。
LibreSSL を選択すると HTTP/2 で ChaCha20-Poly1305 が使えることも魅力です。

HTTP/2 対応では TLS 通信ソフトウェアとして OpenSSL に加えて LibreSSL も有力な候補として検討できるのではないでしょうか。