正規のSSL証明書が無料で自由に使用できる。良い時代になりました・・・、Let’s Encrypt が2016年にリリースされるまではありませんでした。 そんな Let’s Encrypt のSSL証明書ですが、皆さんどうやって取得しているでしょうか? ほとんどの人は Certbot を使って取得や自動更新をしていると思います。 我々も当初は Certbot を使用していました。が、色々あって dehydrated という別のツールを使っています。
目次
なぜdehydrated?
まず Let’s Encrypt を扱う上でクライアントに欲しい機能は以下3点程度だと考えています。 状況によってこれ以外の機能が必要なこともありますが、そういったケースは稀なので特殊なケースとして考えます。
- Web認証で証明書を取得できること
- 証明書の自動更新ができて、サーバーへの反映をおこなえること
- 更新でエラーが発生したときに通知ができること
上記は Certbot でも対応しています。ではなぜ選ぶのか。
dehydrated には余計な機能がないからです。
Certbot には以下の機能などあってリッチなクライアントです。
しかしサーバーの安定運用という点から考えると、コマンドミスで問題を引き起こしかねないものは無いほうが良いです。
- Web認証用にWebサーバーを起動することができる
- 既存の Apache, Nginx に認証用の設定を差し込むことができる
- 各種DNSサービス用のDNS認証にも対応できる
dehydratedの仕様
dehydratedの主な機能は以下になります。
自動更新後のリロードやエラー発生時の通知はBashで書く形になります。
- 認証方式は HTTP-01, DNS-01, TLS-ALPN-01 チャレンジに対応
- マルチドメイン可能
- 複数のバーチャルドメインを一括で対応可能
- エラー発生時や更新後の処理を hook.sh で書くことが可能
Web認証の処理の流れ
Web認証(HTTP-01チャレンジ)の大枠の流れは以下となります。
- サーバーから認証したいドメインを Let’s Encrypt のサーバーへリクエスト
- Let’s Encrypt のサーバーから認証用ファイルを生成するための情報が返ってくる
- サーバー上に認証用ファイルを生成する
- Let’s Encrypt のサーバーから http://example.com/.well-known/acme-challenge/m1x2x-t0x3x といった箇所に認証用ファイルがあるか確認し、中身を検証する
- サーバーにSSL証明書のファイル一式が送られる
動作について詳細がかかれている公式ドキュメントはこちら
https://letsencrypt.org/ja/how-it-works/
実際の設定例
ここではドメインやWebサーバーを以下としておきます、実際に設定するときは別途ご用意ください。
第一ドメイン: main.example.com, www.main.example.com
第二ドメイン: sub.example.com
Webサーバー: Apache
dehydratedの配置と設定
cd /opt
git clone https://github.com/lukas2511/dehydrated.git
vim /opt/dehydrated/domains.txt
---
main.example.com www.main.example.com
sub.example.com
---
vim /opt/dehydrated/config
---
WELLKNOWN="/var/www/dehydrated"
CA="https://acme-v02.api.letsencrypt.org/directory"
---
domain.txt は横に書くとマルチドメインの証明書になり、縦に書くと別の証明書として生成されます。
Web認証用の設定
認証ファイルの配置場所の作成とApacheの許可設定
mkdir -p /var/www/dehydrated/
vim /etc/httpd/conf.d/dehydrated.conf
---
Alias /.well-known/acme-challenge /var/www/dehydrated
<Directory "/var/www/dehydrated">
AllowOverride None
Require all granted
</Directory>
---
apachectl configtest
systemctl reload httpd
SSL証明書の取得
cd /opt/dehydrated/
./dehydrated --register --accept-terms
Let’s Encrypt への登録と利用規約の同意が行われます。
./dehydrated -c
このコマンドでWeb認証のプロセスの開始から終わりまで一括で実行されます。 以下に証明書ファイルが生成されます。
[main.example.com]
SSL証明書: /opt/dehydrated/certs/main.example.com/cert.pem
中間証明書: /opt/dehydrated/certs/main.example.com/chain.pem
秘密鍵: /opt/dehydrated/certs/main.example.com/privkey.pem
中間証明書 + SSL証明書: /opt/dehydrated/certs/main.example.com/fullchain.pem
[sub.example.com]
SSL証明書: /opt/dehydrated/certs/sub.example.com/cert.pem
中間証明書: /opt/dehydrated/certs/sub.example.com/chain.pem
秘密鍵: /opt/dehydrated/certs/sub.example.com/privkey.pem
中間証明書 + SSL証明書: /opt/dehydrated/certs/sub.example.com/fullchain.pem
Apacheの設定で上記SSL証明書のパスの設定をおこない、Apacheをリロードすることで反映されます。 ※Apacheのリロードで証明書の変更が反映できない環境もあります、その場合はリスタートを行ってください。
自動更新設定
自動更新で必要な処理は以下2つ
- 証明書の更新
- Apacheのリロード or エラー通知
※証明書はシンボリックリンクになっており、更新されてもファイルのパスは変わりません。
フック処理の作成
Apacheのリロードやエラー発生時の通知のためのスクリプトを書きます。
cp -p /opt/dehydrated/docs/examples/hook.sh /opt/dehydrated/
vim /opt/dehydrated/docs/examples/hook.sh
---
deploy_cert() {
local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}"
systemctl reload httpd
invalid_challenge() {
local DOMAIN="${1}" RESPONSE="${2}"
{エラー通知処理}
request_failure() {
local STATUSCODE="${1}" REASON="${2}" REQTYPE="${3}" HEADERS="${4}"
{エラー通知処理}
---
フック設定
フックの設定を config に追加する
echo "HOOK=/opt/dehydrated/hook.sh" >> /opt/dehydrated/config
cron設定
cronで以下のような設定をおこないます。
00 5 * * * ( cd /opt/dehydrated; /opt/dehydrated/dehydrated -c ) > /tmp/dehydrated.log 2> /tmp/dehydrated_err.log
テスト
フックが正常に動作するかテストします。
通常は証明書の期限が30日以内にならないと更新されないので、force オプションをつけて実行します。
cd /opt/dehydrated; /opt/dehydrated/dehydrated -c --force
これでApacheがリロードされれば成功です。
おわりに
dehydrated は Bash だけでできているため、インフラエンジニアにとっては非常に扱いやすいです。Let’s Encrypt では自動更新の時によくコネクションタイムアウトで失敗しますが、対策としてアラートを飛ばすのはリトライを数回失敗した後にするといった変更も手軽におこなうことができますし、デバッグもしやすいです。 もし Certbot が使えない環境に巡り合ったときには使ってみてはいかがでしょうか?
一緒に働く仲間を募集しています。
新卒採用・中途採用を問わず、年間を通して、さまざまな職種を募集しています。「すぐに仕事がしたい」「話を聞いてみたい」「オフィスを訪問してみたい」など、ご応募をお待ちしています。共に未来をカタチにする仲間を待っています。