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]
参考
- CentOS 7 + Apache 2.4 で Let's Encrypt の証明書を導入する手順 | WEB ARCH LABO
- Let's Encrypt の使い方 | Let's Encrypt 総合ポータル
証明書の自動更新
先ほど述べたように証明書は 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 && systemctl start httpd.service
最後に
個人情報とか全くやり取りしない中でわざわざ SSL/TLS に適用させる意味があったのか.Google は対応済みのサイトを重視すると言ってはいるらしいですが,程度もよくわかりませんし,成果といえば少し勉強になったことくらいですね.