Let’s Encryptで複数ドメインをまとめてSSL化するよ

某検索エンジンGさんがSSL(TLS)化されてないサイトをクソ扱いするらしいので面倒くせえけど対応します。

まずはCertbotっつーLet’s Encryptのクライアントをサーバにインストールします。

色々なサイトでCentOSならyumで一撃インストールだぜ!みたいなことを書いているけど、ウチのCentは32bitのOS7っつーありえない仕様なのでEPELのリポジトリが対応してません。

なのでここからは少し面倒だけど手作業です。
参考:https://letsencrypt.jp/usage/install-certbot.html

/optにLet’sEncrypt用のディレクトリを作って、そこにソースをオトします。
実行できるようにパーミッションも変更しておきましょう。

mkdir /opt/certbot
cd /opt/certbot
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto

これだけで実行できるので

./certbot-auto

yumとかでインストールできる人は「certbot」ってコマンドらしいけど、ソースで入れた人は代わりに「PATH/certbot-auto」と読み替えてね、と公式ドキュメントにも書いてます。

初回起動時はpythonの実行環境構築や利用規約同意・メアドの要求などがされる。
どのドメインをSSL化する?みたいに聞かれるので「全部」と答えるw

Which names would you like to activate HTTPS for?
-------------------------------------------------------------------------------
1: XXXXXX.net
2: YYYY.XXXXXX.net
3: ZZZZ.XXXXXX.net
-------------------------------------------------------------------------------
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1,2,3

運のいい人はここですんなりSSLキーが生成されるはずです。
勿論私は日頃の行いが悪いのでやはりと言うか、必然的にコケました。

Domain: XXXXXX.net
 Type: connection
 Detail: Fetching
 http://XXXXXX.net/.well-known/acme-challenge/XXXXXXXXXXXXXXXXXXX
 Timeout
To fix these errors, please make sure that your domain name was
 entered correctly and the DNS A/AAAA record(s) for that domain
 contain(s) the right IP address. Additionally, please check that
 your computer has a publicly routable IP address and that no
 firewalls are preventing the server from communicating with the
 client. If you're using the webroot plugin, you should also verify
 that you are serving files from the webroot path you provided.
 - Your account credentials have been saved in your Certbot
 configuration directory at /etc/letsencrypt. You should make a
 secure backup of this folder now. This configuration directory will
 also contain certificates and private keys obtained by Certbot so
 making regular backups of this folder is ideal.

certbotコマンドには色々オプションが有るんですが、
「何をしてもダメ。大人しく死ぬの」みたいな。。。

ドキュメントルートに「.well-known/acme-challenge/」というちょっとエロい名のフォルダが生成されて中のキーをLet’s EncryptのホストがHTTP経由で読みにくるみたいですが、そこがコケてるっぽいです。

ローカルネットワークは勿論外部からもブラウザでアクセスできているし、「そんなはずない」んだけど。

「色々試し」すぎると一定時間にリクエスト飛ばしすぎ、と怒られてアクセスできなくなります。そんな時は1時間ほど食事したり漫画読んだりして時間を潰しましょうw

さて、お腹も一杯になったので今一度ログを確認してみる。

less /var/log/letsencrypt/letsencrypt.log

あれ?IPv6で参照してる??
DNSでIPv6設定してねーわww
※ちなみにサーバ側ではOSのネットワーク設定で有効にさえしておけば賢いプログラムさん達が勝手にIPv4に読み替えてくれます。

念のためAAAAレコードもセットしてDNSを再設定&再チャレンジ。

 ./certbot-auto certonly --webroot -w /[ドキュメントルート1]/ -d XXXXXX.net -d YYYY.XXXXXX.net -w /[ドキュメントルート2]/ -d ZZZZ.XXXXXX.net

おお、通ったわw

上記コマンドの解説をすると、「certonly」はとりあえずSSLキーだけ作って的な。「-w」はドキュメントルートの指定で「-d」は(サブドメインを含む)ドメイン。今回のように1枚の証明書で複数のドメインに対応する場合は-wと-dのペアをスペース区切りで連記すればOK。また「foo.com」と「www.foo.com」みたいにwww有り無しを同じドキュメントルートで対応する場合は-wにセットする-dを上の例の「ドキュメントルート1」のように連記する。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
 /etc/letsencrypt/live/foo.com/fullchain.pem
 Your key file has been saved at:
 /etc/letsencrypt/live/foo.com/privkey.pem
 Your cert will expire on 2018-05-25. To obtain a new or tweaked
 version of this certificate in the future, simply run certbot-auto
 again. To non-interactively renew *all* of your certificates, run
 "certbot-auto renew"

あとは生成されたキーをApacheに組み込みます。

/etc/letsencrypt/live/foo.com/にキーを保存したよ、とのことなので

<VirtualHost *:443>
 SSLEngine On
 DocumentRoot /var/www/www.foo.com
 ServerName foo.com
 ServerAlias www.foo.com
 SSLCertificateFile /etc/letsencrypt/live/foo.com/cert.pem
 SSLCertificateKeyFile /etc/letsencrypt/live/foo.com/privkey.pem
 SSLCertificateChainFile /etc/letsencrypt/live/foo.com/chain.pem
</VirtualHost>

やることはVirtualHostディレクティブに「SSLEngine On」を追記して「cert.pem」「privkey.pem」「chain.pem」の3つを指定。

FirefoxやChromeのURL補完は基本的に「http://」ベースみたいだし、今まで80番で運用していたWEBサーバを丸ごと443に引越しするならリダイレクトの記述も入れておいたほうがいい。

<VirtualHost *:80>
 DocumentRoot /var/www/nonHTTPS
 ServerName localhost
 RewriteEngine On
 RewriteCond %{HTTP_HOST} ^(.*)foo\.com
 RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

こんな感じでOKかと。
SSLの設定が終わったら443ポートの穴あけとhttpdの再起動をお忘れなく。

Let’s Encryptの証明書は90日で有効期限が切れるのでcronで時々更新してやる必要がある。
以下のようなシェルを書いて、月1回キックしてやればいい。(十分に有効期限が残っている場合はスキップしてくれます)

#!/bin/sh
/opt/certbot/certbot-auto renew --post-hook "systemctl restart httpd"

「post-hook」オプションで実行後にApacheを再起動させてます。

以上、お疲れさん。