目標
- Let'sEncryptで以下の4種類のSSL証明書を作る
- シングルドメイン
- マルチドメイン(SANs):同じコンテンツ
- マルチドメイン(SANs):異なるコンテンツ
- ワイルドカード
- 証明書の自動更新もできるようにする
環境
- サーバOS
- CentOS7
- Webサーバ
- apache2.4 + mod_ssl
- ワイルドカード証明書のDNS-01認証に使うDNSサーバ
- さくらのクラウド
準備
certbotをインストールする
yum -y install certbot
epelが未インストールの場合は事前にインストールする必要がある
certbotのバージョンは1.3.0
[root@localhost ~] certbot --version
certbot 1.3.0
シングルドメイン証明書
ドメインとDocumentRoot
ドメインmydomain.foobarはもちろん架空
ドメイン | DocumentRoot |
---|---|
ssl.mydomain.foobar | /var/www/html.ssl |
# SSL化前のApacheの設定
<VirtualHost *:80>
ServerName ssl.mydomain.foobar
DocumentRoot /var/www/html.ssl
</VirtualHost>
証明書作成
certbot certonly \
--webroot -w /var/www/html.ssl -d ssl.mydomain.foobar \
-m <メールアドレス> --no-eff-email \
--agree-tos --manual-public-ip-logging-ok
- certonly
- 証明書の作成を行う(インストールはしない)
- --webroot
- ドメイン認証にHTTP-01を使う
- -w /var/www/html.ssl
- DocumentRootの指定
- -d ssl.mydomain.foobar
- SSL証明書の対象のドメイン
- -m <メールアドレス>
- メールアドレスを登録する。このアドレスに更新案内等のメールが配信される
- --no-eff-email
- EFF(Let'sEncryptのスポンサー団体)からのDMを許可しない。
許可する場合は代わりに --eff-email を指定する。
どちらも指定しなければ、処理中に入力を求められる。 - --agree-tos
- 規約に承認する。
ここで指定しておかないと、処理中に入力を求められる。 - --manual-public-ip-logging-ok
- 実行中のサーバのIPアドレスを記録しても構わないという承認をする。
ここで指定しておかないと、処理中に入力を求められる。
作成された証明書
/etc/letsencrypt/live/ssl.mydomain.foobar/に下記のファイルが作られている
ファイル名 | 用途 |
---|---|
cert.pem | SSL証明書 |
chain.pem | OSCP用中間証明書 |
fullchain.pem | 非OSCP用中間証明書 |
privkey.pem | 秘密鍵 |
# SSL対応のApacheの設定
<VirtualHost *:443>
ServerName ssl.mydomain.foobar
DocumentRoot /var/www/html.ssl
SSLEngine on
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/ssl.mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/ssl.mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/ssl.mydomain.foobar/fullchain.pem
</VirtualHost>
マルチドメイン(SANs):同じコンテンツ
ドメインとDocumentRoot
ドメイン | DocumentRoot |
---|---|
www.mydomain.foobar | /var/www/html.www |
mydomain.foobar | /var/www/html.www |
# SSL化前のApacheの設定
<VirtualHost *:80>
ServerName www.mydomain.foobar
ServerAlias mydomain.foobar
DocumentRoot /var/www/html.www
</VirtualHost>
証明書作成
certbot certonly
--webroot -w /var/www/html.www -d www.mydomain.foobar -d mydomain.foobar \
-m <メールアドレス> --no-eff-email \
--agree-tos --manual-public-ip-logging-ok
- -w /var/www/html.www
- DocumentRootの指定
www.mydomain.foobarとmydomain.foobarで共通 - -d www.mydomain.foobar -d mydomain.foobar
- 証明書を利用するドメインを列挙する
作成された証明書
/etc/letsencrypt/live/www.mydomain.foobar/にシングルドメインの場合と同じファイルが作られている
# SSL対応のApacheの設定
<VirtualHost *:443>
ServerName www.mydomain.foobar
ServerAlias mydomain.foobar
DocumentRoot /var/www/html.www
SSLEngine on
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/www.mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/www.mydomain.foobar/fullchain.pem
</VirtualHost>
マルチドメイン(SANs):異なるコンテンツ
ドメインとDocumentRoot
ドメイン | DocumentRoot |
---|---|
san1.mydomain.foobar | /var/www/html.san1 |
san2.mydomain.foobar | /var/www/html.san2 |
san2.mydomain.foobar | /var/www/html.san3 |
# SSL化前のApacheの設定
<VirtualHost *:80>
ServerName san1.mydomain.foobar
DocumentRoot /var/www/html.san1
</VirtualHost>
<VirtualHost *:80>
ServerName san2.mydomain.foobar
DocumentRoot /var/www/html.san2
</VirtualHost>
<VirtualHost *:80>
ServerName san3.mydomain.foobar
DocumentRoot /var/www/html.san3
</VirtualHost>
証明書作成
certbot certonly
--webroot \
-w /var/www/html.san1 -d san1.mydomain.foobar \
-w /var/www/html.san2 -d san2.mydomain.foobar \
-w /var/www/html.san3 -d san3.mydomain.foobar \
-m <メールアドレス> --no-eff-email \
--agree-tos --manual-public-ip-logging-ok
-w
と-d
の順番が重要
ドメインとドキュメントルートの対応がわかるように、-w -d
の順で正しい組み合わせで繰り返し記述する。
- -w /var/www/html.san1 -d san1.mydomain.foobar
- san1.mydomain.foobar の DocumentRoot は /var/www/html.san1
- -w /var/www/html.san2 -d san2.mydomain.foobar
- san2.mydomain.foobar の DocumentRoot は /var/www/html.san2
- -w /var/www/html.san3 -d san2.mydomain.foobar
- san2.mydomain.foobar の DocumentRoot は /var/www/html.san2
作成された証明書
/etc/letsencrypt/live/san1.mydomain.foobar/にシングルドメインの場合と同じファイルが作られている
最初の-d
で指定したドメインがディレクトリ名に採用される
# SSL対応のApacheの設定
<VirtualHost *:443>
ServerName san1.mydomain.foobar
DocumentRoot /var/www/html.san1
SSLEngine on
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/san1.mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/san1.mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/san1.mydomain.foobar/fullchain.pem
</VirtualHost>
<VirtualHost *:443>
ServerName san2.mydomain.foobar
DocumentRoot /var/www/html.san2
SSLEngine on
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/san1.mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/san1.mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/san1.mydomain.foobar/fullchain.pem
</VirtualHost>
<VirtualHost *:443>
ServerName san3.mydomain.foobar
DocumentRoot /var/www/html.san3
SSLEngine on
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/san1.mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/san1.mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/san1.mydomain.foobar/fullchain.pem
</VirtualHost>
ワイルドカード
方針
-
*.mydomain.foobar
のワイルドカード証明書を作る - ワイルドカードの場合はドメイン認証にHTTP-01は使えず、DNS-01で認証する。
- DNS-01認証のために、mydomain.foobarのDNSで
_acme-challenge.mydomain.foobar
のTXTレコードを登録する必要がある。手作業で登録してもいいのだが、そうすると(おそらく)証明書更新が自動でできない。- 登録する値が毎回変わるため
- 自動更新するためには、そのためのcertbotのプラグインを利用すればよい。プラグインは多数のDNSサーバに対応したものが提供されている。
-
mydomain.foobar
のDNSはプラグインが対応していない。とは言え、DNSサーバ自体を移設するのは何かと大変でやりたくない。 - サブドメイン
_acme-challenge.mydomain.foobar
をプラグイン対応しているDNSサーバに委譲する。プラグイン対応しているDNSサーバ側で、_acme-challenge.mydomain.foobar
のTXTレコードのみを処理してもらうことにする。 - 今回はプラグイン対応DNSサーバとしてさくらインターネットのさくらのクラウドを利用することにする。
- さくらのクラウドのアカウントを元から持っていたことと、DNSサービス利用料が1ゾーン数十円/月のコストで済むことから決定した。
- HTTP-01認証ではないので、証明書作成/更新時にhttp接続可能なWebサーバが起動していないくてもよい。
さくらクラウドの準備
- さくらクラウドのアカウントを作る(持っていない場合)
- DNSサービスにゾーン
mydomain.foobar
を追加作成する - 作成したゾーンのDNSサーバホスト名(2つあるはず)をメモっておく。DNSゾーンの詳細情報ページに書いてある。
- さくらクラウドのAPIキーを作成する。作成したキーの
アクセストークン
とアクセストークンシークレット
をメモっておく。
- 作成するゾーンは
_acme-challenge.mydomain.foobar
ではなくmydomain.foobar
にする、そうしないとプラグインがうまく動かない - ゾーンの作成だけでOK。レコードは必要ない。
- mydomain.foobar自体のDNSをレジストラで変更してはいけない。元のDNSサーバが使えなくなって大惨事になる。
本来のDNSにレコード追加
mydomain.foobarのDNSを管理している本来のDNSサーバに下記のレコードを追加して、_acme-challenge.mydomain.foobar
をさくらクラウドに委譲する。
_acme-challenge IN NS <さくらクラウドのDNSサーバ名1>
_acme-challenge IN NS <さくらクラウドのDNSサーバ名2>
プラグインのインストール
yum -y install python-certbot-dns-sakuracloud
プラグイン用の設定ファイルを用意
プラグインが使用する設定ファイルにさくらクラウドのAPIキー情報を書いて保存する。今回は/root/letsencrypt/sakura_api.conf
というファイル名にする。
設定ファイルのパーミッションは600にしないとプラグインがエラーを吐いて動作しない。
dns_sakuracloud_api_token = "<さくらクラウドAPIキーのアクセストークン>"
dns_sakuracloud_api_secret = "<さくらクラウドAPIキーのアクセストークンシークレット>"
更新時もこのプラグインがこのファイルを読み込むので、うっかり削除してしまわないように、あまり適当な名前にしないほうがよいだろう。
証明書作成
certbot certonly \
--dns-sakuracloud --dns-sakuracloud-credentials /root/letsencrypt/sakura_api.conf \
-d *.mydomain.foobar \
-m <メールアドレス> --no-eff-email \
--agree-tos --manual-public-ip-logging-ok \
- --dns-sakuracloud
- DNS-01認証にさくらクラウドDNS用プラグインを使用する
- --dns-sakuracloud-credentials /root/letsencrypt/sakura_api.conf
- さくらクラウドDNS用プラグインの設定(APIキー情報)ファイルを指定
- -d *.mydomain.foobar
- *.mydomain.foobarのワイルドカード用SSL証明書を作る
作成された証明書
/etc/letsencrypt/live/mydomain.foobar/にシングルドメインの場合と同じファイルが作られている
# SSL対応のApacheの設定
<VirtualHost *:443>
ServerName host.mydomain.foobar
DocumentRoot /var/www/html.host1
SSLEngine on
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/mydomain.foobar/fullchain.pem
</VirtualHost>
<VirtualHost *:443>
ServerName another.mydomain.foobar
DocumentRoot /var/www/html.another
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/mydomain.foobar/fullchain.pem
</VirtualHost>
<VirtualHost *:443>
ServerName any.mydomain.foobar
DocumentRoot /var/www/html.any
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/letsencrypt/live/mydomain.foobar/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.foobar/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/mydomain.foobar/fullchain.pem
</VirtualHost>
課題
本来はさくらクラウドDNSにはmydomain.foobar
ではなく_acme-challenge.mydomain.foobar
のゾーンを作成して運用したかった。
元のDNSから委譲しているのが_acme-challenge.mydomain.foobar
なのに委譲される側のゾーンが不一致なのが気持ち悪いからである。
certbotのさくらクラウドDNS用プラグインで、そうした設定(作成する証明書のドメインとさくらクラウドDNSのゾーンが一致しない)で使用できない(多分)ので、仕方なく今回のような設定にしている。
そもそもRFC的にこの運用が許されるのかどうかも怪しいと思っている。⇒どなたかお教えください。
また、さくらDNSクラウドでゾーンを作成する時に次の注意文が表示される。
作成後表示される当社DNSサーバに対して、権限委譲をお願いします。
なお、1ヶ月以内に委譲がなされない場合、登録が削除されることがあります。
_acme-challenge.mydomain.foobar
は委譲しているがmydomain.foobar
は委譲していないので1ヶ月後にゾーン情報を削除されてしまうかもしれない。
自動更新
Let'sEncryptのSSL証明書は有効期限が3ヶ月と通常の有償のものと比べると短い。
そのため、自動更新できる仕組みを構築しておきたい。
手動で更新するのであれば、シェルから下記のコマンドを実行すればよい。
certbot renew
そのホストで作成したLet'sEncryptの証明書を全て更新できる。
ただし、有効期限が30日以上残っている証明書は更新されない。
上記コマンドで更新すると、新規作成時と同じ設定(HTTP-01認証やDNS-01認証など)で更新処理が行われる。
そのため、新規作成時とDocumentRootが変わっていたりDNS設定が変わっていたりすると更新に失敗するので注意が必要。
自動更新用のスクリプトを用意する。
# !/bin/bash
certbot renew
systemctl reload httpd.service
そのスクリプトをrootのcronで月2回実行する。頻度は運用に合わせて調整してほしい。
0 4 10,25 * * /root/letsencrypt/renew.sh
実際に更新がうまくできるたどうかは、3ヶ月後に追記します
HTTP-01認証のTips
httpsへのリダイレクト
http⇒httpsにリダイレクトしている場合、-wにはhttpsのDocumentRootを指定すればよい。
このとき、httpsの証明書が勝手証明書(mod_sslのデフォルト証明書とか)でも大丈夫。
# http接続をhttps接続にリダイレクト
<VirtualHost *:80>
ServerName www.mydomain.foobar
Redirect temp / https://www.mydomain.foobar/
</VirtualHost>
# https接続のSSL証明書と秘密鍵はmod_sslのデフォルトのもの
<VirutalHost *:443>
ServerName www.mydomain.foobar
DocumentRoot /var/www/html.www
SSLEngine on
### 中略:SSLProtocolとかSSLCipherSuiteとか ###
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
</VirtualHost>
# 証明書作成コマンド
# DocumentRootはhttps://www.mydomain.foobar/のDocumentRoot
certbot certonly
--webroot -w /var/www/html.www -d www.mydomain.foobar \
-m <メールアドレス> --no-eff-email \
--agree-tos --manual-public-ip-logging-ok
DocumentRootの変更
初回のSSL証明書作成時からDocumentRootを変更すると、更新時にHTTP-01認証が失敗する。
この場合は証明書を作り直してしまうか、一度ドキュメントルートを指定し直して手動更新するなどの対応が必要だと思われる。
BASIC認証を掛けている場合
httpアクセスしたとき(あるいは、そこからhttpsにリダイレクトしたとき)にBASIC認証が掛かっていると、SSL証明書の作成/更新ができない。
<VirtualHost *:80>
ServerName basic.mydomain.foobar
DocumentRoot /var/www/html.basic
</VirtualHost>
# BASIC認証
<Directory /var/www/html.basic>
<RequireAll>
AuthName members
AuthType Basic
AuthUserFile /var/www/htpwd/basic
Require valid-user
</RequireAll>
</Directory>
HTTP-01で使用するディレクトリ(/.well-known/acme-challenge)にはBASIC認証がかからないようにすればいいと思われるが、未検証。
特定ユーザ向けサイトなどで、サイト立ち上げの初回の証明書作成時は掛けていないが、運用開始に合わせてBasic認証を掛けた場合に更新ができずにハマりそうである。
参考URL等
下記サイトを参考にさせて頂きました。ありがとうございました。
Let'sEncrypt公式
certbot公式
Let's Encrypt (certbot) でワイルドカード証明書できた!
さくらのクラウド
certbot-dns-sakuracloudのドキュメント(公式じゃないかも?)