Let's Encrypt の証明書をワイルドカードなやつにして自動更新できるようにした
2018 年 3 月,ついに Let's Encrypt がワイルドカードな証明書の発行に対応したので,所有するサーバの証明書をワイルドカードなものにリプレイスしてみました. 今まではサブジェクト代替名でサブドメインを列挙するスタイルをとっていて地味に面倒だったのと,証明書を読むと internal 向けのドメインがバレちゃうというのがあり,ワイルドカードな証明書に置き換えることでこれらを解決することができました.
この記事のゴール
この記事では以下について述べます.今回作業する環境は ArchLinux ですが,certbot と certbot の cloudflare プラグインのパッケージさえあれば他の OS も動くと思います.
ksswre.net
と*.ksswre.net
の証明書を manual モードで取得する- 上で取得した証明書を自動更新できるようにする (自動更新のため CloudFlare の Free プランを併用)
試行錯誤をしながら作業を行ったので 1 時間弱くらいかかりましたが,最終的にはワイルドカードな証明書が certbot renew
で自動更新できるようになりました.
前提
certbot を使います.ArchLinux なので pacman -S certbot
すると certbot が降ってきた気がします.なければいれましょう.
ワイルドカードな証明書を取得する
おもむろに以下のコマンドをうちます.ワイルドカード証明書を取得するには dns-01 認証が必要なので,manual モードにして認証形式を手動で設定します.
また,2018 年 4 月現在でワイルドカード証明書を発行するには ACME v2 が必要なので --server
オプションを付けて認証サーバを変更します.メールアドレスや IP アドレスを記録するが良いかなどとインタラクティブな操作で確認されるので Y か N を打って答えます.
# certbot certonly --manual -d '*.ksswre.net' -d ksswre.net -m 'mail@example.com' --agree-tos --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory
しばらくすると以下のような画面がでます.これは dns-01 認証のためのもので,ドメインを本当に所有しているかどうか DNS の TXT にワンタイムトークンを追加することで認証します.
------------------------------------------------------------------------------- Please deploy a DNS TXT record under the name _acme-challenge.ksswre.net with the following value: XXXXXXXXXXXXXXXXXXXXXXXXXXXX Before continuing, verify the record is deployed. ------------------------------------------------------------------------------- Press Enter to Continue
ドメイン管理画面を開き (以下は StarDomain の例),ワンタイムトークンを DNS の TXT レコードに追記します.
追記したら Enter を押します.うまいこといくと以下のような表示があるはずです.
Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/ksswre.net-0002/privkey.pem Your cert will expire on 2018-07-05. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
これより,サーバ証明書などが取得できたので nginx.conf
を編集し,証明書を新しいものに切り替えます.nginx.conf
の抜粋.
ssl_certificate /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ksswre.net-0002/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/ksswre.net-0002/chain.pem;
Nginx を再起動すると,うまいこといってるのがわかります.Postfix や Dovecot の設定なども同様にお忘れなくやりましょう.
このままでは自動更新できない
証明書が更新できるか確認しましょう.--force-renewal
オプションを付けて強制更新モードにして一旦走らせてみると,エラーでコケることがわかります.
# certbot renew --force-renewal Saving debug log to /var/log/letsencrypt/letsencrypt.log ------------------------------------------------------------------------------- Processing /etc/letsencrypt/renewal/ksswre.net-0002.conf ------------------------------------------------------------------------------- Could not choose appropriate plugin: The manual plugin is not working; there may be problems with your existing configuration. The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',) Attempting to renew cert (ksswre.net-0002) from /etc/letsencrypt/renewal/ksswre.net-0002.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration. The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',). Skipping. All renewal attempts failed. The following certs could not be renewed: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem (failure)
manual モードの場合はインタラクティブな操作が必要で certbot renew
で更新するには --manual-auth-hook
オプションで認証用ホックを自前で用意する必要があるそうです.ホックを自前で書くのは面倒なので調べてみたら,certbot の CloudFlare プラグインを使う方法があるそうです.以下のサイトが有用でしたので参考にさせていただきました.
a244.hateblo.jp
CloudFlare プラグインを併用して自動更新する
CloudFlare プラグインを使うためには,既存のネームサーバを CloudFlare に変更する必要がありますが,CloudFlare に変更すると DNS TXT レコードの書き換えと dns-01 認証をプラグインが全て自動で行ってくれます.便利です.CloudFlare は個人サイトの規模であれば Free プランで十分なので,無料で運用できます.
このプラグインを使うには,ArchLinux では新しいパッケージをインストールする必要があるのでインストールしておきます.
# pacman -S certbot-cloudflare
上のサイトを参考にしながら CloudFlare でアカウントをとり,ネームサーバを CloudFlare に変更し,管理パネルの Get your API key から Global API Key を取得し,certbot に設定しておきます.CloudFlare の CDN (Proxy) は今回は必要ないのでオフにしておき,ネームサーバだけ有効にしておきます.
設定ができたら,certbot で上のセクションで取得した証明書をリニューアルします.以下のコマンドを走らせます.
# certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -d ksswre.net -d '*.ksswre.net' --server https://acme-v02.api.letsencrypt.org/directory
プラグインとして CloudFlare 用のものが選択されていることがわかります.
Plugins selected: Authenticator dns-cloudflare, Installer None Cert not yet due for renewal
しばらくすると,既に同じドメインで取得した証明書をリプレイスして良いか聞いてくるので,そうしてもらいます. そのあと少し放置すると,CloudFlare のネームサーバを通して dns-01 認証を行われ,正常に証明書が更新されます. この間,上のセクションで使用した manual モードのようにインタラクティブな操作は発生せず,全て自動で進みます.便利.
You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry. (ref: /etc/letsencrypt/renewal/ksswre.net-0002.conf) What would you like to do? ------------------------------------------------------------------------------- 1: Keep the existing certificate for now 2: Renew & replace the cert (limit ~5 per 7 days) ------------------------------------------------------------------------------- Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2 Renewing an existing certificate Performing the following challenges: dns-01 challenge for ksswre.net dns-01 challenge for ksswre.net Waiting 10 seconds for DNS changes to propagate Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/ksswre.net-0002/privkey.pem Your cert will expire on 2018-07-05. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
これで CloudFlare プラグインを使ってワイルドカードな証明書が自動更新できるようになりました.
# certbot renew --force-renewal Saving debug log to /var/log/letsencrypt/letsencrypt.log ------------------------------------------------------------------------------- Processing /etc/letsencrypt/renewal/ksswre.net-0002.conf ------------------------------------------------------------------------------- Plugins selected: Authenticator dns-cloudflare, Installer None Renewing an existing certificate Performing the following challenges: dns-01 challenge for ksswre.net dns-01 challenge for ksswre.net Waiting 10 seconds for DNS changes to propagate Waiting for verification... Cleaning up challenges ------------------------------------------------------------------------------- new certificate deployed without reload, fullchain is /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem (success) -------------------------------------------------------------------------------
この後は,certbot renew
を定期的に投げれば良いので,crontab や systemd-timer を使って定期的にコマンドが走るようにします.これで自動更新は完成です.