VPS+ApacheにSSL/TLSを導入する

Let's Encrypt というサービスを利用することで,無料でサーバ証明書を発行することができるようです.スポンサーには Cisco, Hewlett Packard Enterprise などがいるので,それなりに安心して使えると思います.

SSL/TLS

詳しい説明は他に譲りますが,パスワードなどが漏れずに安全にサイトへ接続するため暗号化した通信をするためのプロトコルです.TLS が強度的にも推奨されていますが,昔からの名残で SSL と呼ばれることもたくさんあるようです.

サーバ証明書は普通数千円くらいするので,弱小個人サイトではなかなか手を出しにくいですが,このようなサービスもあるんですね.サーバ証明書もセキュリティ証明書とか呼ばれたりしていますが,これも混同しててよくわからんです...

複数サイトへの適用

バーチャルホスト設定を利用していてサイトが複数ある場合でも,サブドメインでは同じ証明書が使えます.(ワイルドカード証明書)

しかし,ホスト名が全く異なる場合=ドメインが全く異なる場合は利用できません.HTTP サーバに対して一つしか使えないからです.そのため,バーチャルホスト設定で複数のドメインを同一サーバに向けているなら,どのドメインに SSL/TLS を当てるか決めておく必要があります.

Let's Encrypt

環境

  • CentOS7
  • Apache2.4.6

インストール

Certbot クライアントのインストール自体は簡単です.

yum search certbot でパッケージが出ない場合,epel とやらをインストールしてあげる必要があります.

terminal
# yum install epel-release
# yum install certbot python2-certbot-apache

root もしくは sudo で実行します.

サーバ証明書の発行

証明書のタイプがドメインを所有していることを確認するドメイン認証なので,証明書の発行に 80 番ポートと 443 番ポートを利用します.もちろん 80 番ポートと 443 番ポートが開放されていないと使えません.(80 番が閉じててハマりかけ…)

ポート開放の方法はこちらで確認してください.→ VPS に Apache, MySQL, firewall を設定する

Web サーバを停止したら発行に移ります.

terminal
# certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com

-d オプションでドメインを追加できます.ここでは例として example.com, www.example.com に発行します.

実行がスタートし,更新がなければメールアドレスの入力,規約への同意が行われます.メールアドレスは緊急通知や証明書の期限の通知などに使われるようです.

terminal
# systemctl restart httpd.service

発行後したら忘れずに Apache を再起動します.

サーバ証明書の保存場所

サーバ証明書の本体は /etc/letsenrypt/archive/example.com 以下にあります.サーバ証明書,中間証明書,それらを統合した証明書,秘密鍵の 4 ファイルが生成されますが,Apache のバージョンや Nginx など別の Web サーバで使うものが異なります.

Apache 2.4.8 以前の場合はサーバ証明書 (cert.pem) ,中間証明書 (chain.pem) ,秘密鍵 (privkey.pem) の 3 ファイルが必要です.また,証明書は 90 日で切れるので再発行が必要ですが,再発行することにファイル名に含まれる数字が変わるため,本体の名前ではなくシンボリックリンクを設定に使います.

SSL/TLS の設定

ssl.conf の編集

terminal
# vim /etc/httpd/conf.d/ssl.conf

設定ファイル内の三項目を次のように書き換えます.

ssl.conf
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem

vhost.conf の編集

私はバーチャルホスト設定を使って複数のサイトを構成しているので,vhost.conf も編集します.

vhost.conf
<VirtualHost *:443>
    DocumentRoot /var/www/html/example
    ServerName example.com
    ServerAlias www.example.com
    CustomLog logs/ssl-example-access.log common
    ErrorLog  logs/ssl-example-error.log
    AddDefaultCharset UTF-8

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
    <Directory "/var/www/html/example/">
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

以前は一つの IP アドレスに対して証明書一枚だったようですが,SNI のおかげでホスト名ごとに発行することができるようになったらしいです.

SSLCertificateChainFile の記述がない設定も見かけましたが,スマホのブラウザではエラーになるので必要なようです.

ここまで書き換えたら Apache を再起動します.

terminal
# systemctl restart httpd.service

これで https://example.com で接続できたら,ひとまず完了です.

HTTPS への転送

www の有無に関する転送は vhost.conf でなんとかなりますが,HTTP から HTTPS への転送は .htaccess でやるしかなさそうです.

.htaccess
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

参考

証明書の自動更新

先ほど述べたように証明書は 90 日しか持たない,しかし手作業で毎回更新するのも大変であるということで自動で更新している人が多いようですが,ここで問題発生.上の方法だと certbot-auto がないぞ?と一瞬めんどくさくなりました.

terminal
# certbot -h renew

ヘルプに載ってました.(一安心)

以下のコマンドでテストできます.

terminal
# certbot renew --dry-run

cron 設定

Linux には cron 設定があるので,それを活用して自動実行というのがメジャーなようです.crontab で操作すればいいらしいことはわかりましたが,詳しい設定なんかは眠くてよく分かりません.動かなかったら頑張ります.

0 4 31 * * systemctl stop httpd.service
1 4 31 * * certbot renew &amp;&amp; systemctl start httpd.service

最後に

個人情報とか全くやり取りしない中でわざわざ SSL/TLS に適用させる意味があったのか.Google は対応済みのサイトを重視すると言ってはいるらしいですが,程度もよくわかりませんし,成果といえば少し勉強になったことくらいですね.