2018/09/16
Let's Encryptでワイルドカード証明書を発行する
今回は「さくらのVPS」で Linux OS (CentOS - RedHat6 final) を使っているということもあり、certbot-auto が使えてます。
え?今まではどうやってるのかって?

手動でやってんだよ!!!!

マジクソ面倒臭い。
でも certbot-auto にしても微妙に面倒臭いのは変わりない。 意外と楽でした。



と、その前に。

証明書をインストールしたはいいが、不正な証明書だと言われたら cert.pem から fullchain.pem に変更しよう。
というか fullchain.pem の方がなにかと良い結果になる。
これは OS やブラウザに Let's Encrypt の中間証明書が入っていないのが原因なので、証明書に中間証明書を混ぜ込んでしまう。
# 今回は K-9 Mail でおおはまり。



結論から言うと「Amazon Route53 使ってるならワイルドカードの自動更新は (説明が多いから) 簡単だけど、他の DNS を使ってるならば「どうやればいいのか」を探すところから始めなければならないのでとても面倒くさい。
# 一応、認証方式に Dynamic DNS を使った更新 (certonly → --dns-rfc2136) は有る。

もうワイルドカード使わずに webroot のオーセンティケーター (Apache の Web 型承認) でいいんじゃね?と思う次第。



まずは基本。
  • -m は忘れずに!(期限が近づいてきたらメールで知らせてくれる)
  • 指定した基本的なオプションは conf ファイルに保存される。--staging や --post-hook なども全て。ただし revoke の時は --staging は付ける必要有り。どんなオプションが保存されているかは /etc/letsencrypt/renewal/*.conf を見よう。
  • 更新は certbot-auto renew と叩くだけ。あとは certbot-auto が良きに計らってくれる。複数のドメインを別の証明書で作った場合は --cert-name で CN の名前を指定する。
  • 使い終わった証明書はステージング環境であっても revoke しておこう。まぁ期限が来たら勝手に消えると思うけど。
使い方。
certbot-auto に勝手に証明書をインストールさせないために、サブコマンドは "certonly" を使用すること。
このサブコマンドは証明書を発行して貰いサーバーの /etc/letsencrypt/ に保存するだけのコマンド。
install とか run とか使うとどこかにインストールされてしまうので注意。

httpd が起動している Web サーバーで証明書を発行してみよう。
% sudo certbot-auto certonly --webroot \
    -m [自分のメールアドレス] \
    -w [ホスト名に対するディレクトリルート] \
         -d ホスト名 \
    --manual-public-ip-logging-ok
例)
% sudo certbot-auto certonly --webroot \
    -m [自分のメールアドレス] \
    -w /home/www/defaultroot/public_html/ \
         -d www.example.com \
    -w /home/www/test/public_html/ \
         -d test.example.com \
    --manual-public-ip-logging-ok
オプションの順序は関係ないと思うけど、オーセンティケーターに webroot を使うなら -w を先に書いて -d は後ろに書いた方がいいかもしれない。
# 説明ではそうなってるし。
複数のドメインを含めるならば -w -d -w -d … と続く。

本番機に何度もリクエストを投げるとアクセス制限を食らうので、使い方がよくわからないな〜という人や動きを確認したいだけならば --staging を付けて実行。
これは制限の緩いテスト環境 (conf ファイルでは server = https://acme-staging-v02.api.letsencrypt.org/directory の 1行がある) を使用するオプション。



certbot-auto の使い方は「Let's Encrypt ユーザーガイド」を参照すること。
「コマンド解説(コマンドリファレンス)」は旧式の使い方なので、参考にはなるけど増えてるオプションの解説が無い。



まず前提条件。
ワイルドカードとネイキッドドメインのホスト名部別扱いになる。つまり
example.com ≠ *.example.com
となる。
なので *.example.com の証明書を発行しても example.com の証明書にはならないということ。
# *.example.com だけの証明書を持つサーバーに example.com でアクセスすると不正な証明書になる。
# example.com が記述されていないので当然ではあるが。



テストをする際は最新の certbot-auto だと ACME v2 に対応しているので
% sudo certbot-auto certonly --manual --staging \
    -m [メールアドレス] -d "*.自ドメイン" \
    --manual-public-ip-logging-ok --force-renewal
でテスト可能。

例)
% sudo certbot-auto certonly --manual --staging \
    -m [メールアドレス] -d "*.example.com" \
    --manual-public-ip-logging-ok --force-renewal
説明。
  • オーセンティケーターは手動 (--manual)
  • ステージング環境を使用する (--staging)
  • グローバルIPアドレスを認証局でロギングすることに対する確認を表示しない (--manual-public-ip-logging-ok)
  • 期限が残っていようが問答無用で再発行する (--force-renewal)
--dry-run を着けない場合は既存の証明書が無効な証明書 (=いわゆる「証明機関で証明されていない無効な証明書」俺俺証明書みたいな感じ) で上書きされるが、その場合は先にバックアップを取っておくか、素直に上書きしてあとから正規の証明書を作り直す。
本番で使ってるなら気をつけてね!!
ここで重要なのは

--staging を着けるとテストモードになる。

なんでテストをするのかって?
ちゃんと証明書の発行が出来るか、更新が出来るかを確認するために。
本番環境では証明書発行・更新の回数制限があるので要注意。
なおテストモードは制限がかなり緩い。
詳しくはこちらを。
制限と仕様からLet's Encrypt(ACMEv1)の話



更新するときは certbot-auto renew を実行。
これだけ。すごいかんたん。
証明書の更新時期が来てなければ certbot-auto が勝手に判断して更新せずに終了。
えらい。

cron に登録しておこう。

なお、1つのサーバー上で複数の証明書を管理している場合は --cert-name で CN の名前を指定すると良い。

例)
% sudo certbot-auto renew --cert-name 2nd.example.com
CN とは簡単に言うと証明書が持つメインとなるドメイン名で、-d の一番初めに指定したドメイン名が該当する。
/etc/letsencrypt/ のディレクトリに証明書が格納されている各ディレクトリ名がそれ。



本番環境で作成した証明書を消す場合は、Lets Encrypt サーバーに置いてある履歴を消す必要があるので revoke 処理を行う。
ステージング環境を使用した場合は必ず --staging を付けること。
% sudo certbot-auto revoke --cert-path [fullchain.pem のフルパス]
例)
% sudo certbot-auto revoke \
    --cert-path /etc/letsencrypt/live/www.example.com/fullchain.pem
revoke しても再作成 (再申請) は可能。

消さなくても期限が超えたら消えると思う…。



オーセンティケーターに --manual を選んだとき、ドメイン使用権の認証方式に DNS 認証を使うならば "--preferred-challenges dns" を着ける。
(デフォルトは http)
% sudo certbot-auto certonly --manual --staging \
    -m [メールアドレス] -d [ホスト名] \
    --manual-public-ip-logging-ok \
    --force-renewal --preferred-challenges dns



さて、自ドメインにサブドメイン切って --preferred-challenges dns による自動更新を行ってみる。
参考にしたのは

Certbotによるワイルドカード証明書と自動更新の設定

だが、dns-01 スクリプトの書式に間違いがあったので修正している。
# nsupdate に渡すコマンドの先頭に update の記述が無いので "delete メソッドなんぞ知らぬ!" と怒られる。


まずは Dynamic DNS の準備。
Dynamic DNS のゾーンは分けておかないと元のゾーンが Dynamic DNS によりぐちゃぐちゃにされるのでちゃんと分ける。
以下のように親のゾーンである griffonworks.net. から権限委譲して別ファイルにすると良い。
TSIG 鍵は nsupdate -l で運用する (ローカルホスト限定) ので今のところは不要。
$ORIGIN griffonworks.net.
$TTL 86400
@ IN SOA leviathan.griffonworks.net. root.griffonworks.net. (
:
(省略)
:
ddns IN NS sakura.griffonworks.net.
[ /var/named/dynamic/ddns_griffonworks_net.zone ]
$ORIGIN ddns.griffonworks.net.
$TTL 60
@ IN SOA leviathan.griffonworks.net. root.griffonworks.net.
                            ( 2018091800 10800 600 604800 60 )
                        NS      ns.griffonworks.net.
named.conf は "_" (アンダーバー/アンダースコア) を使用するので "check-names ignore" は必要。
[ /etc/named.conf ]
zone "ddns.griffonworks.net" {
        type master;
        file "/var/named/dynamic/ddns_griffonworks_net.zone";
        allow-update { localhost; };
        check-names ignore;
};
この時、/var/named/dynamic/ddns_griffonworks_net.zone のパーミッションは named が更新する必要があるので named:named に chown しておくこと。
 # mkdir /var/named/dynamic/
 # chown named:named /var/named/dynamic/
 # chmod 770 /var/named/dynamic/
 # vi /var/named/dynamic/ddns_griffonworks_net.zone
 # chown named:named /var/named/dynamic/ddns_griffonworks_net.zone
 # chmod 644 /var/named/dynamic/ddns_griffonworks_net.zone
テストするなら以下のように。
ちゃんと
ホスト名  TTL値  IN  TXT  値
書式でないと受け付けられません。
% nsupdate -l
> update add test.ddns.griffonworks.net. 10 IN TXT "teststrings"
> send
> (CTRL+D で抜ける)

% dig TXT test.ddns.griffonworks.net.
;; ANSWER SECTION:
test.ddns.griffonworks.net.  10 IN TXT  "teststrings"

% nsupdate -l
%gt; update delete test.ddns.griffonworks.net.
%gt; send
> (CTRL+D で抜ける)

% dig TXT test.ddns.griffonworks.net.
(返信無し)

今度は certbot-auto。
まずは前準備としてフック用のスクリプトを用意。
参考:certbot User Guide - Pre and Post Validation Hooks
実行属性は付けておいてください。
オーナーはてきとー。

[ /etc/letsencrypt/renewal-hooks/dns-01-auth.sh ]
#!/bin/sh

# certbot-auto を実行すると CERTBOT_VALIDATION に認証キーがセットされる。
[ "$CERTBOT_VALIDATION" = "" ] && exit 0

# nsupdate を localhost モード (-l) で動かす。
cat <<_TXT_ | nsupdate -l
update delete _acme-challenge.${CERTBOT_DOMAIN}. IN TXT
update add _acme-challenge.${CERTBOT_DOMAIN}. 10 IN TXT "${CERTBOT_VALIDATION}"
send
_TXT_
[ /etc/letsencrypt/renewal-hooks/dns-01-clean.sh ]
#!/bin/sh
cat <<_CMD_ | nsupdate -l
update delete _acme-challenge.${CERTBOT_DOMAIN}. IN TXT
send
_CMD_
まずは初回の証明書発行。
ちゃんとステージング環境 (--staging) で試しましょう。
% sudo certbot-auto certonly \
    -m [自分のメールアドレス] \
    --preferred-challenges dns \
    --staging \
    --manual \
    --manual-public-ip-logging-ok \
    -d "*.ddns.griffonworks.net" \
    --manual-auth-hook /etc/letsencrypt/renewal-hooks/dns-01-auth.sh \
    --manual-cleanup-hook /etc/letsencrypt/renewal-hooks/dns-01-clean.sh 
説明。
  • ドメイン使用権の認証方法に DNS の TXT レコードを使用する (--preferred-challenges dns)
  • 認証の承認リクエストを受けた時に実行するスクリプト (--manual-auth-hook)
  • 認証の承認リクエストを受けた後に実行するスクリプト (--manual-cleanup-hook)
実行結果。
% sudo certbot-auto 〜
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for ddns.griffonworks.net
Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/ddns.griffonworks.net/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/ddns.griffonworks.net/privkey.pem Your cert will expire on 2018-12-17. 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"
もしスクリプトにエラーがあったらちゃんとエラーが出る。
スクリプトで何をやってるか気になるなら nsupdate -l にパイプしてる内容を一時ファイルに書き出し、一時ファイルを nsupdate に喰わせるスクリプトに変更して、一時ファイルを cat してみると良い。

普段は renew を実行するだけで良い。
% sudo certbot-auto renew --cert-name ddns.griffonworks.net --staging 
試しに強制的に証明書を更新 (--force-renewal) してみる。
% certbot-auto renew --cert-name ddns.griffonworks.net --force-renewal
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/ddns.griffonworks.net.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Plugins selected: Authenticator manual, Installer None
Renewing an existing certificate
Performing the following challenges:
dns-01 challenge for ddns.griffonworks.net
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/ddns.griffonworks.net/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/ddns.griffonworks.net/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

% openssl x509 -text -in ./live/ddns.griffonworks.net/cert.pem | more
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Fake LE Intermediate X1
        Validity
            Not Before: Sep 18 04:26:13 2018 GMT
Not After : Dec 17 04:26:13 2018 GMT
Not Before: が現在の時間になっていることが確認出来る (夏時間に注意)。
ちなみに "Issuer: CN=Fake LE Intermediate X1" はステージング環境のこと。
本番だと "Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3" になる。

いろいろお試しが終わったら revoke しておきましょう。
% sudo certbot-auto revoke --staging \
    --cert-path /etc/letsencrypt/live/ddns.griffonworks.net/fullchain.pem
このフック機能、"certbot User Guide - Pre and Post Validation Hooks" を見ると http にも対応しているので、scp とノーパスの鍵を組み合わせれば certbot-auto 実行サーバーと Web サーバーを分離出来たりするが、それはまた別のお話。

なお、ネイキッドドメインの DNS 認証については、先に紹介したい「Certbotによるワイルドカード証明書と自動更新の設定」の開設で _acme-challenge ゾーンを個別に切って (権限委譲で分離) Dynamic DNS ゾーンにすることで対応出来た。
% sudo certbot-auto certonly \
    -m griffon@griffonworks.net \
    --staging --manual --manual-public-ip-logging-ok \
    -d "*.griffonworks.net" -d griffonworks.net \
    --preferred-challenges dns \
    --manual-auth-hook /etc/letsencrypt/renewal-hooks/dns-01-auth.sh \
    --manual-cleanup-hook /etc/letsencrypt/renewal-hooks/dns-01-clean.sh


最終:2018/09/18 13:37:20 カテゴリ:
タグ:鯖管理
  - NO COMMENT -
QRコード
携帯サイト試験運用
https://griffonworks.net/nikki/cgi-bin/k.cgi
1行板

備忘録
  • 無し
物欲リスト
  • Canon RF50mm F1.2L USM
  • SIGMA 20mm F1.4 EF Art
  • ニンバス チヌーク
  • OCB-1 ST II
ツーリング ドライブ兼野外撮影予定リスト