Let’s Encrypt の証明書作成をDNS-01チャレンジで行う

外部公開していないWebサーバーでLet’s Encryptの証明書を利用したい

非公開 or アクセス制限を施したWebサーバにおいて、Let’s Encryptの証明書を利用したいケースがあり、一般的に広く使われている HTTP-01 チャレンジでは不都合が多かったので、DNS-01チャレンジでの作成方法を調べてみました。

IPアドレス制限なら、HTTP-01 チャレンジで使われるIPアドレスを許可すれば良いだろうと思ったものの、利用されているIPアドレスは非公開ということなので断念。

定期的に更新するときだけ、アクス制限を解除して手動で更新するのも何だかなあという感じだったので、DNSを利用した手法を試してみました。

DNS-01チャレンジで証明書を作成する

公式サイトにあるとおり、DNS-01チャレンジでは利用しているDNSサービスがAPIを提供していると自動化までスムーズにできるようです。

公式サイトのリストには載っていませんが、私が利用しているGehirnDNSもAPIが利用可能です。

さらに、Certbotでも専用のプラグインが用意されているので、こちらで試してみました。

使用したOSは Rocky Linux release 8.6 (Green Obsidian) です。

Certbotプラグインのインストール

$ yum search gehirn
メタデータの期限切れの最終確認: 1:09:32 時間前の 2022年06月01日 17時16分29秒 に実施しました。
===================================================== 名前 & 概要 一致: gehirn ======================================================
python-certbot-dns-gehirn-doc.noarch : Documentation for python-certbot-dns-gehirn
python3-certbot-dns-gehirn.noarch : Gehirn Infrastructure Service DNS Authenticator plugin for Certbot

$ sudo yum install python3-certbot-dns-gehirn.noarch
メタデータの期限切れの最終確認: 2:14:41 時間前の 2022年06月01日 13時34分29秒 に実施しました。
依存関係が解決しました。
=====================================================================================================================================
 パッケージ                                  アーキテクチャー        バージョン                     リポジトリー               サイズ
=====================================================================================================================================
インストール:
 python3-certbot-dns-gehirn                  noarch                  1.22.0-1.el8                   epel                        22 k
依存関係のインストール:
 python3-dns-lexicon                         noarch                  3.3.17-2.el8                   epel                       336 k
 python3-future                              noarch                  0.18.2-2.el8                   epel                       790 k
 python3-requests-file                       noarch                  1.4.3-5.el8                    appstream                   15 k
 python3-tldextract                          noarch                  2.2.3-1.el8                    epel                        66 k

トランザクションの概要
=====================================================================================================================================
インストール  5 パッケージ

ダウンロードサイズの合計: 1.2 M
インストール後のサイズ: 4.8 M
これでよろしいですか? [y/N]: y
パッケージのダウンロード:
(1/5): python3-certbot-dns-gehirn-1.22.0-1.el8.noarch.rpm                                            369 kB/s |  22 kB     00:00    
(2/5): python3-requests-file-1.4.3-5.el8.noarch.rpm                                                  171 kB/s |  15 kB     00:00    
(3/5): python3-dns-lexicon-3.3.17-2.el8.noarch.rpm                                                   3.0 MB/s | 336 kB     00:00    
(4/5): python3-tldextract-2.2.3-1.el8.noarch.rpm                                                     1.0 MB/s |  66 kB     00:00    
(5/5): python3-future-0.18.2-2.el8.noarch.rpm                                                        6.5 MB/s | 790 kB     00:00    
-------------------------------------------------------------------------------------------------------------------------------------
合計                                                                                                 510 kB/s | 1.2 MB     00:02     
トランザクションの確認を実行中
トランザクションの確認に成功しました。
トランザクションのテストを実行中
トランザクションのテストに成功しました。
トランザクションを実行中
  準備             :                                                                                                             1/1 
  インストール中   : python3-future-0.18.2-2.el8.noarch                                                                          1/5 
  インストール中   : python3-requests-file-1.4.3-5.el8.noarch                                                                    2/5 
  インストール中   : python3-tldextract-2.2.3-1.el8.noarch                                                                       3/5 
  インストール中   : python3-dns-lexicon-3.3.17-2.el8.noarch                                                                     4/5 
  インストール中   : python3-certbot-dns-gehirn-1.22.0-1.el8.noarch                                                              5/5 
  scriptletの実行中: python3-certbot-dns-gehirn-1.22.0-1.el8.noarch                                                              5/5 
  検証             : python3-requests-file-1.4.3-5.el8.noarch                                                                    1/5 
  検証             : python3-certbot-dns-gehirn-1.22.0-1.el8.noarch                                                              2/5 
  検証             : python3-dns-lexicon-3.3.17-2.el8.noarch                                                                     3/5 
  検証             : python3-future-0.18.2-2.el8.noarch                                                                          4/5 
  検証             : python3-tldextract-2.2.3-1.el8.noarch                                                                       5/5 

インストール済み:
  python3-certbot-dns-gehirn-1.22.0-1.el8.noarch    python3-dns-lexicon-3.3.17-2.el8.noarch    python3-future-0.18.2-2.el8.noarch   
  python3-requests-file-1.4.3-5.el8.noarch          python3-tldextract-2.2.3-1.el8.noarch     

完了しました! 

Gehirn WebサービスのAPIクライアントを登録

Gehirnのサイトにログインして、ダッシュボード→APIクライアントからAPIクライアントを登録して、静的鍵の情報を取得します。

APIクライアントの設定から静的鍵を作成

DNSの情報が変更できるよう管理権限を与えます。閲覧者権限は不要かも。

ロール割当でDNSの閲覧・管理権限を付与する

certbot-dns-gehirnの設定

ドキュメントがあるので参考に設定します。プラグイン自体の設定はシンプルで、GehirnDNSのAPIにおける鍵ID/ユーザ名およびシークレット/パスワードを設定ファイルとして保存してやるだけです。

ドキュメントサイトを参考に設定ファイルを作成します。

$ sudo vi /root/.secrets/certbot/gehirn.ini
dns_gehirn_api_token  = 鍵ID/ユーザ名
dns_gehirn_api_secret = シークレット/パスワード

他者に読み取られないようにパーミッションを適切に設定しないと、Certbot実行時に注意されます。が、普通に動きます。

CertbotのGehirnDNS用プラグインを利用して省力・自動化する

$ sudo certbot certonly --dns-gehirn --dns-gehirn-credentials /root/.secrets/certbot/gehirn.ini -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for www.example.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/www.example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/www.example.com/privkey.pem
This certificate expires on 2022-08-30.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

無事、作成が完了しました。

あとは適当なWebサーバーで利用するように設定すればOK。

自動更新のテスト

証明書の更新テストを行います。本来なら30日以内にならないと動作しないため強制的に実施する --force-renewal オプションを付けて実行しています。

$ sudo certbot renew --force-renewal --dry-run 
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/www.example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for www.example.com
Waiting 30 seconds for DNS changes to propagate

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded: 
  /etc/letsencrypt/live/www.example/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

無事、Congratulations, all simulated renewals succeeded:と表示されました。

あとはCronに組み込んで定期的に実行すれば、アクセス制限されていても、DNS-01 チャレンジで更新がされます。

閉じた環境で使いたいケースがどれくらいかは分かりませんが、できるようになっていると便利かと。

自動更新するためにはAPI提供されているDNSサービスの利用が必要なので、自前のDNSでの管理だったりすると少し手間がかかるかもしれないですね。