Let’s Encrypt でSSLワイルドカード証明書を導入する

Archlinuxが動いているRaspberryPi君にワイルドカード証明書を導入する。
特段、難しいことはなく、Qiita等々で書かれていたことをトレースしただけだった

前提

入ってるもの
MyDNS
・RaspberryPi鯖

# cat /etc/os-release 
NAME="Arch Linux ARM"
PRETTY_NAME="Arch Linux ARM"
(中略)
# certbot --version
certbot 1.12.0
# date +%Y%m%d_%H%M
20210221_0503

今あらためて気づいたんだけど、Archlinuxってarch-releaseって何も書いてないんだね
CentOSで作業するときのversion番号確認作業がたまにあるんだが、そのときはredhat-releaseを参照してversion番号確認をしている。
少なくともCentOS8はredhat-releaseは/etc/centos-releaseのシンボリックリンクで、今どきな人の中でCentOS使ったことない人も考えると、redhat-releaseを参照するという手順は難しいんじゃないかな?と思ったり
話がすぐ逸れる

ワイルドカード証明書を発行する

Let’s Encryptでもワイルドカード証明書は対応している
が、v2 APIのURLを指定する必要がある。

certbot certonly --manual \
    --preferred-challenges dns \
    --server https://acme-v02.api.letsencrypt.org/directory \
    -m hoge@unko.com \
    -d *.meto4d.pgw.jp

実行すると、以下のような表示が出る

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Requesting a certificate for *.meto4d.pgw.jp
Performing the following challenges:
dns-01 challenge for meto4d.pgw.jp

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.meto4d.pgw.jp with the following value:

xxxxxxx(ランダムな文字列)

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Enter入力待になるが、DNSレコードが必要なので(MyDNS用に)ブラウザで作業
途中のxxxxxxx(ランダムな文字列) はメモってMyDNSへ

MyDNSにTXTレコードで_acme-challenge.meto4d.pgw.jpを登録する
_acme-challenge.meto4d.pgw.jp   TXT   xxxxxxx
MyDNSは反映が早いとはいえ、1分ぐらい待ったほうが懸命だろう。
反映したかdigコマンドで確認する

% dig @ns0.mydns.jp _acme-challenge.meto4d.pgw.jp -t TXT

; <<>> DiG 9.16.10 <<>> @ns0.mydns.jp _acme-challenge.meto4d.pgw.jp -t TXT
(中略)
;; ANSWER SECTION:
_acme-challenge.meto4d.pgw.jp. 300 IN   TXT     "xxxxxxx"

→一応Googleでも確認
% dig @8.8.8.8 _acme-challenge.meto4d.pgw.jp -t TXT

; <<>> DiG 9.16.10 <<>> @8.8.8.8 _acme-challenge.meto4d.pgw.jp -t TXT
(中略)
;; ANSWER SECTION:
_acme-challenge.meto4d.pgw.jp. 299 IN   TXT     "xxxxxxx"

反映されていたので、certbotに戻ってEnter

....(上のcertbot作業の続き)
Press Enter to Continue [[Enter]]
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/meto4d.pgw.jp-0001/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/meto4d.pgw.jp-0001/privkey.pem
   Your certificate will expire on 2021-05-21. 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

認証が出来ていた

ちょっと待て

  Your key file has been saved at:
   /etc/letsencrypt/live/meto4d.pgw.jp-0001/privkey.pem

meto4d.pgw.jpの証明書はある
*.meto4d.pgw.jpのワイルドカード証明書がmeto4d.pgw.jp-0001に?
気持ち悪いのでmeto4d.pgw.jp-wildにでも移動してもらう

lets encrypt配下のarchive, live内の meto4d.pgw.jp-0001 を移動し、renewal/のconf内を変更していく

(なんか少し怖かったので、sudo su - したshell以外でやった)
% cd /etc/letsencrypt

→証明書の中身を移動
% cd archive
% sudo mv -r  meto4d.pgw.jp-0001 meto4d.pgw.jp-wild
% cp ../live
% sudo mv -r  meto4d.pgw.jp-0001 meto4d.pgw.jp-wild
% cd meto4d.pgw.jp-wild
% ls -l
(抜粋)
lrwxrwxrwx 1 root root  42  2月 21 05:59 cert.pem -> ../../archive/meto4d.pgw.jp-0001/cert1.pem
→シンボリックリンクが前のままなので、変更
% /bin/ls -1 *.pem | xargs -i sh -c "readlink {} | sed 's/0001/wild/g' | xargs -I [] sudo ln -nfs [] {}"
→実はlnのtargetとlink先の順番を間違えて一回消しちゃったw
上書きしてしまったarchiveのmeto4d.pgw.jp-wildをディレクトリ毎消して、certbot certonly --manualを再実行
dns等々はしてあるので、TXTの書き換えもなく即終了
% ls -l
(抜粋)
lrwxrwxrwx 1 root root  42  2月 21 06:42 cert.pem -> ../../archive/meto4d.pgw.jp-wild/cert1.pem

→設定を変更
% cd renewal
% cat meto4d.pgw.jp-0001.conf
# renew_before_expiry = 30 days
version = 1.12.0
archive_dir = /etc/letsencrypt/archive/meto4d.pgw.jp-0001
cert = /etc/letsencrypt/live/meto4d.pgw.jp-0001/cert.pem
privkey = /etc/letsencrypt/live/meto4d.pgw.jp-0001/privkey.pem
chain = /etc/letsencrypt/live/meto4d.pgw.jp-0001/chain.pem
fullchain = /etc/letsencrypt/live/meto4d.pgw.jp-0001/fullchain.pem
(中略)

% sudo sed -i 's/meto4d.pgw.jp-0001/meto4d.pgw.jp-wild/g' meto4d.pgw.jp-0001.conf
% sudo mv meto4d.pgw.jp-0001.conf meto4d.pgw.jp-wild.conf

→これでいいはず……
(certbotを動かしていたterminalに戻って)
# certbot renew
(抜粋)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/meto4d.pgw.jp-wild.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

→特にエラーはないので、これで大丈夫…かな?

Nginxでワイルドカードを使ってみる

nginx/server.confにまとめているので、そこで

ローカル用のデバッグポートに追記
server {
  listen 10080;
  include conf.d/default_ssl.conf;
  ssl_certificate /etc/letsencrypt/live/meto4d.pgw.jp-wild/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/meto4d.pgw.jp-wild/privkey.pem; # managed by Certbot
  include conf.d/default_proxy.conf;
  include conf.d/php_fcgi_location.conf;
  location / {
    index index.test.php;
  }
}
% sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
% sudo systemctl reload nginx 

構文チェックしろとよく言われるようになったので、最近ちゃんとnginx -tをしてからreloadするようになった
今までの、まあ大丈夫だろうでrestartして鯖を止めてた時代からは進歩した
確認は無意識でできるようになったが、確認した後、面倒くさって言ってる気がする

ブラウザでアクセスしてみる

まじかよ!

*.meto4d.pgw.jpは meto4d.pgw.jpに使えないってそんなことあるのか

再発行する

% sudo certbot certonly --manual \
    --preferred-challenges dns \
    --server https://acme-v02.api.letsencrypt.org/directory \
    -m hoge@unko.com \
    -d *.meto4d.pgw.jp \
    -d meto4d.pgw.jp
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
You have an existing certificate that contains a portion of the domains you
requested (ref: /etc/letsencrypt/renewal/meto4d.pgw.jp.conf)

It contains these names: meto4d.pgw.jp

You requested these names for the new certificate: *.meto4d.pgw.jp,
meto4d.pgw.jp.

Do you want to expand and replace this existing certificate with the new
certificate?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(E)xpand/(C)ancel: e
Renewing an existing certificate for *.meto4d.pgw.jp and meto4d.pgw.jp
An unexpected error occurred:
requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='acme-v02.api.letsencrypt.org', port=443): Read timed out. (read timeout=45)
Please see the logfiles in /var/log/letsencrypt for more details.

どうもv2 APIではexpand出来ないみたいだ
だからといってタイムアウトはどうなんだとは思ったが
既存設定を削除する必要がある

既存設定を削除

# certbot delete
Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which certificate(s) would you like to delete?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: meto4d.pgw.jp-wild
4: meto4d.pgw.jp

適当に抜粋
今しがた作ったmeto4d.pgw.jp-wildとmeto4d.pgw.jpを削除

再発行(2度目)

→最後の -d meto4d.pgw.jp を追加
% sudo certbot certonly --manual \
    --preferred-challenges dns \
    --server https://acme-v02.api.letsencrypt.org/directory \
    -m hoge@unko.com \
    -d *.meto4d.pgw.jp \
    -d meto4d.pgw.jp
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Requesting a certificate for *.meto4d.pgw.jp and meto4d.pgw.jp

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/meto4d.pgw.jp/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/meto4d.pgw.jp/privkey.pem
   Your certificate will expire on 2021-05-21. 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の設定再変更

さっき変更したばっかりのmeto4d.pgw.jp-wild部分を元に?戻す

ssl_certificate /etc/letsencrypt/live/meto4d.pgw.jp/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/meto4d.pgw.jp/privkey.pem; # managed by Certbot

reloadの類いをするした

ブラウザでアクセス

雑スクショだが、ちゃんとワイルドカードで証明書を出せている
いいね!

後は晒せないNginxの設定をワイルドカードに対応させていく

nginxの仕様上、ifで証明書を分けているとそのたびにsslを紐解くらしく、結構遅くなるらしい
どれぐらい遅くなるかは試していないが、以下のようにしていた

server {
  listen 443 ssl;
  server_name "" _;
  include conf.d/localssl.conf;
  include conf.d/ip_location.conf;
}
server {
  listen 443 ssl;
  server_name meto4d.pgw.jp;
  ssl_certificate /meto4d.pgw.jp/....
  ssl_certificate_key /meto4d.pgw.jp/....
  include conf.d/default_location.conf;
}
server {
  listen 443;
  server_name auto.meto4d.pgw.jp;
  ssl_certificate /auto.meto4d.pgw.jp/....
  ssl_certificate_key /auto.meto4d.pgw.jp/....
  include conf.d/default_location.conf;
}
(適当に端折)

公開鯖の都合上、IP直打ちで来る人も多い
(例えばterraria鯖をIPで晒していると、結構IPをブラウザに突っ込んで来る人がいるんだ)
そういう人にこの鯖に簡単にはたどり着けないようにしたいため、設定を変えている
localssl.confは自己署名証明書を読み込むやつ

server_name meto4d.pgw.jp; と server_name auto.meto4d.pgw.jp; で冗長な構成になっていた
ここを整理
v6とv4、dsは残しておく

まとめ

導入は簡単だったが、結局replace作業になったのでちょっと面倒だった
ワイルドカードにとうとうやったので、将来VPSとかk8sで管理するときに楽になったね


ref: let’s EncryptのワイルドカードSSL証明書を取得する。 – nhmasaazu
ref: ACME v2 Production Environment & Wildcards – API Announcements – Let’s Encrypt Community Support

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)