Ideal Reality

パソコンのある生活を良くするためのサイト

MyDNSでLet’s Encryptのワイルドカード証明書を自動更新する

最近TLS(SSL)必須のAPIやライブラリが多いですよね。自宅サーバーにテスト環境を構築してサブドメインでアクセスするのにいちいち証明書作ってらんないので、ワイルドカード証明書にしたかったんです。

スポンサーリンク

HTTP-01とDNS-01

まず、TLS証明書を取得するにはドメインの所有権を確認する必要があります。

HTTP-01とは、HTTPサーバーのにACMEクライアントが発行したトークンを設置、それをLet’s Encryptが外部からアクセスしてトークンを検証することで、ドメインの所有者を確認する方法です。

Let’s Encryptの設定方法を調べたら出てくる記事のほとんどはこの方法を利用しており、僕が当ブログで公開しているWordpress設定方法の記事でもこのやり方を書いてます。

HTTP-01はHTTPサーバーに所定のファイルを設置する(もしくはcerbotの検証用サーバーを使用する)だけで検証可能であり、つまりは手元のサーバーをいじるだけで設定できるのでとても簡単です。

ですが、この方法ではサブドメインの所有権までは確認できないので、ワイルドカード証明書は発行できません。

そこで使用するのがDNS-01です。

DNS-01ではACMEクライアントが発行したトークンをDNSのTXTレコードに設置します。

DNSはドメインツリーと呼ばれる階層構造になっているため、1つのドメインの所有権が確認できればそのサブドメインの所有権も同じく確認できるわけです。

ただし、DNSのTXTレコードが存在するのは手元のサーバーではなく、名前解決を行っているネームサーバーなので、certbotで証明書を取得する度にネームサーバーにトークンを設定する必要があります。

MyDNSのLet’s Encrypt用API

DNSのTXTレコードをマニュアルでしか設定できないネームサーバーだと、証明書更新を毎回マニュアルで行わなければいけなくてとっても面倒なのですが、MyDNSではDNS-01での証明書取得を自動化できるようにAPIを提供してくれています。

https://github.com/disco-v8/DirectEdit/

これを使えば簡単にワイルドカード証明書の取得を自動化できる・・・のですが複数のMyDNSアカウントを扱えないのと、PHPってのがどうも気に入らなかったのでPythonで書き換えました。

import urllib.parse
import urllib.request
import base64
import sys
import os

def mydns_register_validation(master_id, password, domain, validation, cmd = "REGIST"):
	url = "https://www.mydns.jp/directedit.html"
	authorization = master_id + ":" + password
	headers = {
		"Content-Type": "application/x-www-form-urlencoded",
		"Authorization": "Basic " + base64.b64encode(authorization.encode()).decode("utf-8")
	}
	data = {
		"EDIT_CMD": cmd,
		"CERTBOT_DOMAIN": domain,
		"CERTBOT_VALIDATION": validation
	}
				
	request = urllib.request.Request(url, headers=headers, data=urllib.parse.urlencode(data).encode(), method="POST")
	try: urllib.request.urlopen(request)
	except urllib.error.HTTPError as e:
		print(e.code)
		print(e.read())
スポンサーリンク

使い方

Pythonスクリプトの用意

https://gist.github.com/Hiroki-Kawakami/301ddcec49dff9423753fdbe00120c54

ここからmydns_register.pyをダウンロードして、ファイルの末尾にあるmydns_register_validation関数呼び出しのMyDNS Master IDとパスワードを書き換えてください。

Pythonスクリプトの配置

スクリプトを配置する場所はrootアカウントから実行できればどこでもいいです。

僕はMyDNSのLet’s Encript用APIの使い方に従って、証明書が保管されているドメインのディレクトリに配置しました。/etc/letsencrypt/live/example.comのような場所です。

所有者とグループはroot、パーミッションは700がいいです。

証明書の取得

まずはちゃんと動作するか–dry-runで確認します。

sudo certbot certonly \
--dry-run \
--manual \
--agree-tos \
--no-eff-email \
--manual-public-ip-logging-ok \
--preferred-challenges dns-01 \
--server https://acme-v02.api.letsencrypt.org/directory \
--domain example.com \
--domain *.example.com \
--email address@example.com \
--manual-auth-hook "/etc/letsencrypt/live/example.com/mydns_register.py" \
--manual-cleanup-hook "/etc/letsencrypt/live/example.com/mydns_register.py DELETE"

ドメインとメールアドレス、pythonスクリプトのパスは自分のものに書き換えてくださいね。

成功したら本番で、–dry-runを抜いて実行してください。

自動更新

環境にもよりますが、大体は証明書を取得するのにcertbotを実行した時にsystemdのcertbot-renew.timerが有効化されているはず。

systemctl list-timers

上記のコマンドでsystemdのタイマー一覧を確認できるので、certbot-renew.timerがスケジューリングされているか確認してください。

もし有効化されていないなら

sudo systemctl enable --now certbot-renew.timer

で有効化できます。

まとめ

MyDNSのAPIが扱いやすく、また反映も速いため思った以上に簡単にできました。

これでテスト環境用にサブドメインを作りまくれます。

スポンサーリンク

参考

チャレンジのタイプ – Let’s Encrypt – フリーな SSL/TLS 証明書

Let’s Encrypt ワイルドカード自動更新(ConoHa)

スポンサーリンク

コメント

投稿されたコメントはありません

名前

コメント

関連する投稿

VagrantのWebサーバーをmDNSでLAN内からアクセスできるようにしてみた

MyDNSでスタードメインを使用する