LibreSSL で SSL/TLS 対応の Webサーバを設定する（CentOS編）

通常、Linux ディストリビューションでは、SSL/TLS 通信ソフトウェアとして OpenSSL がインストールされています。
そのような環境で [LibreSSL](http://www.libressl.org/) と組み合わせて Webサーバを設定するにはどうすればよいでしょうか。
OpenSSL は様々なプログラムとリンクされているため、単純に OpenSSL を削除して代わりに LibreSSL をインストールするだけだと不都合が生じます。
既存の OpenSSL はそのまま、既存のプログラムもそのまま、Webサーバのプログラムだけを LibreSSL と組み合わせて使うというのはいかがでしょうか？

ここでは CentOS7 (x86_64) 上で LibreSSL を Apache 及び Nginx と組み合わせて使うための設定について調べてみます。

---

# はじめに

## 基本となる考え
ここで検証しようとしたことの基本となる考えは、後付けの LibreSSL と Apache 及び Nginx を /usr/local/ 配下に置く、というだけのものです。
通常、パッケージ機能でインストールされる OpenSSL やそれとリンクされている Webサーバは /usr/ 配下に置かれているので、お互いに干渉しなくて済むと考えました。
これだけのことなので、今回は CentOS7 で検証しましたが、他のディストリビューションでも同様のことができると思います。

## この文章の構成について
この文章では、Apache ＋ LibreSSL の手順と Nginx ＋ LibreSSL の手順を各々独立して書いています。
各々の手順を通して読めるようにですが、このため各々の手順の中で重複する箇所があります。

# Apache ＋ LibreSSL の設定手順
[Apache HTTP サーバ](https://httpd.apache.org/) バージョン 2.4.20 で確認しました。
[LibreSSL](http://www.libressl.org/) のバージョンは 2.4.0 です。

## (1) ビルド手順
まずは LibreSSL をビルドして /usr/local/ 配下にインストールします。

```shell-session
# tar xf libressl-2.4.0.tar.gz
# cd libressl-2.4.0
# ./configure
# make check
# make install
```

次に Apache をビルドして /usr/local/apache2 配下にインストールします。
LibreSSL をインストールした /usr/local を configure のオプションで指定しています。

```shell-session
# tar xf httpd-2.4.20.tar.gz
# cd httpd-2.4.20
# ./configure --enable-ssl --with-ssl=/usr/local
# make
# make install
```

## (2) 設定
設定ファイルを編集して、SSL/TLS 通信の設定を行います。
以下で示す３箇所の行の、先頭の '#' を削除しています。

```bash:/usr/local/apache2/conf/httpd.conf
... <略> ...
     89 LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
... <略> ...
    131 LoadModule ssl_module modules/mod_ssl.so　modules/mod_lbmethod_byrequests.so
... <略> ...
    483 Include conf/extra/httpd-ssl.conf
... <略> ...
```
(ここでは動作確認をするためだけの最小限の設定を示しています。)

## (3) サーバの秘密鍵と証明書を作る
LibreSSL の `openssl` コマンドを使って秘密鍵とサーバ証明書(自己署名証明書、いわゆるオレオレ証明書)を生成します。

```shell-session
# PATH=/usr/local/bin:${PATH}
# openssl genrsa -out server.key 2048
# openssl req -new -key server.key -out server.csr
# openssl x509 -days 30 -req -signkey server.key -in server.csr -out server.crt
```

## (4) サーバの秘密鍵と証明書を配置する
上で生成したサーバの秘密鍵と証明書を所定のディレクトリに置きます。

```shell-session
# mv server.key /usr/local/apache2/conf/
# mv server.crt /usr/local/apache2/conf/
```
これで設定は完了です。

## (5) 動作確認
`/usr/local/apache2/bin/apachectl start` で起動して SSL/TLS 接続できるか動作確認してみます。

### Web ブラウザで接続してみる
https (443番ポート) にアクセスすると、テスト用 Web ページの "It works!" を確認できるはずです。

### s_client で接続してみる
SSL/TLS での通信を確認するために `openssl s_client` で接続してみます。
暗号スイートとして 'CHACHA20' も指定してみました。

```shell-session
# /usr/local/bin/openssl s_client -port 443 -cipher 'CHACHA20'
... <略> ...
---
SSL handshake has read 1632 bytes and written 378 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-CHACHA20-POLY1305
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-CHACHA20-POLY1305
... <略> ...
```
TLSv1.2 と ECDHE-RSA-CHACHA20-POLY1305 で接続できていることを確認できました。

# Nginx ＋ LibreSSL の設定手順
[Nginx](http://nginx.org/) バージョン 1.11.1 で確認しました。
[LibreSSL](http://www.libressl.org/) のバージョンは 2.4.0 です。

## (1) ビルド手順
まずは LibreSSL をビルドして /usr/local/ 配下にインストールします。

```shell-session
# tar xf libressl-2.4.0.tar.gz
# cd libressl-2.4.0
# ./configure
# make check
# make install
```

次に Nginx をビルドして /usr/local/nginx 配下にインストールします。
Nginx はビルド時に LibreSSL のソースコードの場所を指定する必要があります。
ここでは、libressl-2.4.0/ と nginx-1.11.1/ のディレクトリは同じディレクトリ階層にあるものとします。

```shell-session
# tar xf nginx-1.11.1.tar.gz
# cd nginx-1.11.1/
# ./configure --prefix=/usr/local/nginx --with-http_ssl_module \
  --with-openssl=../libressl-2.4.0
# make
# make install
```

## (2) 設定
設定ファイルを編集して、SSL/TLS 通信の設定を行います。
以下に示す箇所の、行の先頭の '#' を削除しています。

```bash:/usr/local/nginx/conf/nginx.conf
... <略> ...
     96     # HTTPS server
     97     #
     98     server {
     99         listen       443 ssl;
    100         server_name  localhost;
    101
    102         ssl_certificate      cert.pem;
    103         ssl_certificate_key  cert.key;
    104
    105         ssl_session_cache    shared:SSL:1m;
    106         ssl_session_timeout  5m;
    107
    108         ssl_ciphers  HIGH:!aNULL:!MD5;
    109         ssl_prefer_server_ciphers  on;
    110
    111         location / {
    112             root   html;
    113             index  index.html index.htm;
    114         }
    115     }
... <略> ...
```
(ここでは動作確認をするためだけの最小限の設定を示しています。)

## (3) サーバの秘密鍵と証明書を作る
LibreSSL の `openssl` コマンドを使って秘密鍵とサーバ証明書(自己署名証明書、いわゆるオレオレ証明書)を生成します。

```shell-session
# PATH=/usr/local/bin:${PATH}
# openssl genrsa -out server.key 2048
# openssl req -new -key server.key -out server.csr
# openssl x509 -days 30 -req -signkey server.key -in server.csr -out server.crt
```

## (4) サーバの秘密鍵と証明書を配置する
上で生成したサーバの秘密鍵と証明書を所定のディレクトリに置きます。

```shell-session
# mv server.key /usr/local/nginx/conf/cert.pem
# mv server.crt /usr/local/nginx/conf/cert.key
```
これで設定は完了です。

## (5) 動作確認
`/usr/local/nginx/sbin/nginx` で起動して SSL/TLS 接続できるか動作確認してみます。

### Web ブラウザで接続してみる
https (443番ポート) にアクセスすると、テスト用 Web ページの "Welcome to nginx!" を確認できるはずです。

### s_client で接続してみる
SSL/TLS での通信を確認するために `openssl s_client` で接続してみます。
暗号スイートとして 'CHACHA20' も指定してみました。

```shell-session
# /usr/local/bin/openssl s_client -port 443 -cipher 'CHACHA20'
... <略> ...
---
SSL handshake has read 1536 bytes and written 298 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-CHACHA20-POLY1305
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-CHACHA20-POLY1305
... <略> ...
```
TLSv1.2 と ECDHE-RSA-CHACHA20-POLY1305 で接続できていることを確認できました。

# まとめ
CentOS 上での LibreSSL を使った Webサーバの設定を、Apache 及び Nginx でやってみました。最新版を使ったこともあり、ビルドはエラーなく行えました。

今後、OpenSSL に深刻な問題が出た場合、LibreSSL は良き代替案となるでしょう。また LibreSSL でのみ実装されている機能を気軽に試してみられる環境も整いました。LibreSSL を利用することのハードルはデフォルトでインストされていないことだけかもしれません。