世界を動かす技術を、日本語で。

DNS-Persist-01: DNSベースのチャレンジ検証のための新しいモデル

概要

  • Let's Encryptが新しいACMEチャレンジ方式 DNS-PERSIST-01 を導入予定
  • 従来の DNS-01 方式に比べて運用コストを削減
  • 永続的な認証レコード で再検証不要
  • セキュリティや運用上の利点と注意点
  • 2026年 Q2に本番展開 を予定

Let's Encryptの新しいACMEチャレンジ方式:DNS-PERSIST-01

  • Let's Encryptは、証明書発行時に ACMEチャレンジ を用いたドメイン所有権検証を実施
  • ワイルドカード証明書やインターネット非公開インフラ向けには、従来 DNS-01 チャレンジが唯一の選択肢
  • DNS-01 は広く普及し実績も豊富だが、DNS伝播遅延や更新作業、DNS認証情報の配布など運用コストが高い
  • 新たに DNS-PERSIST-01 方式を実装予定
    • IETFドラフト仕様に基づく
    • DNSを使った検証だが、 永続的な認証レコード を利用
    • ACMEアカウントとCAに紐づけて認証を維持

DNS-01方式の特徴と課題

  • DNS-01 は、毎回新しいトークンをTXTレコードで公開し、その都度検証
  • 各発行時にDNS更新が必要となり、DNS API認証情報の管理と配布が不可欠
  • 大規模運用では、DNS伝播待ちや頻繁なDNS変更の負担が大きい
  • セキュリティ上、DNS書き込み権限の管理が重要

DNS-PERSIST-01方式の仕組み

  • 一度だけ 認証用TXTレコード をDNSに公開
    • 例: _validation-persist.example.com. IN TXT ( "letsencrypt.org;" " accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890" )
  • レコードが存在すれば、新規発行や更新時に再利用可能
  • 運用上、証明書発行パイプラインからDNS更新作業を排除
  • 認証は ACMEアカウント に紐づくため、DNS認証情報の配布範囲を限定可能

セキュリティと運用上のトレードオフ

  • DNS-01 :DNS書き込み権限が最大のリスク
  • DNS-PERSIST-01 :認証はアカウントキーに依存し、DNS書き込み権限は初回のみ必要
  • 永続的なレコードのため、 ACMEアカウントキーの保護 が最重要課題

認証範囲と有効期間の管理

  • デフォルトでは、検証済みFQDNのみが有効
  • ワイルドカード証明書の場合、policy=wildcardを追加
    • 例: _validation-persist.example.com. IN TXT ( "letsencrypt.org;" " accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890;" " policy=wildcard" )
  • 有効期限を制限したい場合、persistUntilパラメータで設定
    • 例: _validation-persist.example.com. IN TXT ( "letsencrypt.org;" " accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1234567890;" " persistUntil=1767225600" )
  • 複数CA同時認証も可能、TXTレコードを複数設置

導入スケジュールと対応状況

  • CA/Browser Forumの SC-088v3 が2025年10月に可決、IETFドラフトも同時採択
  • Pebble(Boulderの軽量版)でドラフト仕様のサポート開始済み
  • lego-cliクライアントの実装も進行中
  • 2026年 Q1にステージング環境展開、Q2に本番展開 予定

DNS-PERSIST-01導入のメリットと注意点

  • DNS更新作業や認証情報配布の省力化
  • IoTやマルチテナント環境、大量証明書発行に最適
  • 永続レコード利用時は ACMEアカウントキーの厳格管理 が必須
  • 有効期限設定時は、期限切れ防止の監視やリマインダー運用が必要

Hackerたちの意見

これ、実際の運用上の痛点を解決してると思う。私も経験したことがあるから。唯一の懸念は、管理アカウントのIDが直接露出することかな。アカウントのキー素材を守る必要があるわけじゃないけど、それはもうやってるしね。「ユーザー名」は一般的に認証情報ほど保護されてないけど、重要なゲートとして機能するから、攻撃が始まる前に知っておく必要がある。これによって、見つけたランダムな認証情報を、同じアカウントを使っているサイトに関連付けることができるのも大きい。これって、発生した侵害に対する無料のスコープ拡張だよね。Shodanみたいなサイトが、見ているすべてのドメインでこれらのIDをインデックスし始めることを保証するよ。

その通り!ユーザーには、アカウントURIのURLで使えるUUID(または実際のアカウントに結びついた他のランダムなID)のリストを提供すべきだね。

アカウントは、どのacmeクライアントでも作成するものと同じだよ。リバースルックアップの可能性は見えないな。

CAAレコードにアカウントURIが含まれていると、同じようにアカウントのIDが露出してしまうから、その船はもう出てしまった感じがするな(CAAと持続レコードのフォーマットが一致することを望んでいるけど)。

これを見て本当に嬉しい!その間、bindを権威あるネームサーバーとして使っているなら、hmac-secretを1つのTXTレコードに制限できるから、rfc2136を使って証明書を更新する各ウェブサーバーは、自分の特定のレコードだけを更新できるんだ。例えば、こんな感じでね。 key "bob.acme." { algorithm hmac-sha512; secret "blahblahblah"; }; key "joe.acme." { algorithm hmac-sha512; secret "blahblahblah2"; }; zone "example.com" IN { type master; file "/var/lib/bind/example.com.zone"; update-policy { grant bob.acme. name _acme-challenge.bob.acme.example.com. TXT; grant joe.acme. name _acme-challenge.joe.acme.example.com. TXT; }; key-directory "/var/lib/bind/keys-acme.example.com"; dnssec-policy "acme"; inline-signing yes; }; これが好きなのは、攻撃者が「bob」を侵害しても、「bob」用の証明書しか取得できないからだよ。サーバー部分はこんな感じ。 export LE_CONFIG_HOME="/etc/acme-sh/" export NSUPDATE_SERVER="${YOUR_NS_ADDR}" export NSUPDATE_KEY="/var/lib/bob-nsupdate.key" export NSUPDATE_KEY_NAME="bob.acme." export NSUPDATE_ZONE="acme.example.com." acme.sh --issue --server letsencrypt -d 'bob.example.com'
--certificate-profile shortlived
--days 6
--dns dns_nsupdate

HTTP-01検証メソッドを使ったIPアドレス証明書で何ができるかを見た後、短命の証明書について考えが変わったよ。もう証明書をディスクに書き込むことすらしない。現在の証明書のインスタンスがnullか24時間以上古いかをチェックするバックグラウンドスレッドがあるから、aspnetcoreの証明書セレクターはこの参照を見て、nullじゃなくなるまでブロックするんだ。ユーザーに自己ホスト可能なソフトウェアを配布できて、VMにデプロイして実際に5分以内に運用開始できるのは大きなセールスポイントだよ。ドメイン登録とDNSは、初心者にとっては本当に面倒なことだしね。これをhttps://checkip.amazonaws.comみたいなものと組み合わせて、ちゃんとしたターンキーソリューションを作れるよ。

Let's Encryptのレート制限が交渉できないって考えると、かなりリスキーだよね。待つしかないし。

証明書はどこかに保存しておくべきだよ。そうしないと、あなたの可用性がLEの稼働時間に大きく依存しちゃうから。

やったー!これで内部専用のウェブサービスの証明書が、ACME以前よりも実際に簡単に管理できるようになるはず。これが、私がletsencryptや現代のウェブ証明書で抱えていた最大の運用上の痛点を解決すると思う。関わった皆さんに本当に感謝!

ここに欠けている部分があって、それはACMEアカウントの所有権を確認することなんだ。ほとんどのユーザーは、自動化されたアカウント作成に依存しているから、これに対処する必要がないんだよね。でも今は、ACMEプロバイダーにアカウントの所有権を確認するための認証情報を伝播させる必要がある。これについての議論がこの発表にあったらよかったな。Let's Encryptの認証モデルには詳しくないけど、ターゲットドメインによって制限できるトークン作成がないなら、各ターゲットドメイン用に別々のアカウントを作成する必要があると思う。そうしないと、その秘密を持っているものであれば、アカウントが管理するどのドメインでも証明書を作成できちゃうから。

ここに欠けてる部分があって、それは自分のACMEアカウントの所有権を確認することだよ。なんでかって?ACMEアカウントには認証情報があって、ACMEクライアントが証明書発行者に対して認証できるようになってるんだ。ACMEプロバイダーは、アカウントがドメインの所有者の要求に応じて行動する権限があるかどうかを確認するために、DNSレコードや.well-known HTTPエンドポイントの設置を求めるんだ。もしACMEの認証情報が漏れたり、さらに悪いことに、誰かがDNSレコードを置いたり、あなたの.well-knownエンドポイントをハイジャックしたりしたら、SSL証明書をあなたのドメイン名で不正に発行されるよりも、もっと大きな問題が発生することになるよ。

これで、インターネットに接続されていないLANサーバー用の公的に信頼された証明書を取得するのがめっちゃ楽になるね。どの管理者UIでも、DNSレコードにペーストするだけでLet's Encryptの証明書がすぐに取得できるようになるのを楽しみにしてるよ。

自分のネットワークが複雑なopenclawのセットアップでこれを経験したばかり。もう諦めて、もっと時間ができるまで手動で更新することにした。headscaleのマジックDNSセットアップ用の証明書を取得しようとしてたんだけど、思ってたよりもずっと複雑だと思う。

俺、何か大事なことを見逃してるのかな?理論的には、俺のドメインのDNSサーバーをコントロールしてる人や、LEとそのDNSサーバー間のトラフィックをコントロールしてる人が、俺のドメインを偽装するためのTLS証明書を取得できるってことになるよね?DNS-01でも同じことが言えると思うけど、攻撃者が自分のLEアカウントをDNSレスポンスに入れれば証明書を取得できるから、さらに簡単になるよね。だったら、公開証明書をDNSレコードに入れてしまえばいいんじゃない?

そう、あなたのDNSをコントロールしてる人は、誰でもTLS証明書を取得できるよ。だって、彼らがあなたのDNSをコントロールしてるからね!もし私があなたのDNSを変更できるなら、TLS証明書を取得するのを妨げる方法を考えてみてよ。

もしあなたがDNSプロバイダーを信頼できないなら、その関係にはいるべきじゃないよ。もし誰かがLetsEncryptとDNSサーバーの間でMITM攻撃を仕掛けられるなら、証明書の発行だけの問題じゃなくなるからね。

もし私があなたのDNSをコントロールしてたら、HTTP Acmeチャレンジも簡単にできるよ。あなたがDNSをコントロールしてるなら、基本的にそれはあなたのドメインだしね。

証明書発行者とDNSサーバーの間のネットワークを攻撃者が制御している場合の脅威を軽減するために、CAは複数の視点からDNSレコードを確認するんだ。Let's Encryptはこれを数年間やってきていて、2024年からはすべてのCAにとっての要件になってるよ。[1] https://cabforum.org/2024/08/05/ballot-sc067v3-require-domai...

certbotを使ってる人向けに、この機能のサポートに関する作業が追跡されてる場所はここだよ: https://github.com/certbot/certbot/issues/10549

LEから権威あるネームサーバーに送信されるDNSリクエストが暗号化されていないのは本当なの?

自分のLEの経験(HTTP-01からDNS-01に移行した後)だけど、ちょっと面倒だね。ポート80を開ける必要がないのはセキュリティ監査にはいいけど、セキュリティ上のメリットはゼロだよ。ローカルでNAT経由で静的IPv4アドレスを持つPowerDNSサーバーを運用していて、特定のIPv4アドレスからの動的DNS更新を許可するDNSドメインを作成したんだ。各証明書には特定の形式で自分のDNSドメインを指すDNS CNAMEが必要なんだよね。それから、実際に作業をするためのソフトウェアに慣れなきゃいけない。acme.shはWindows以外では素晴らしいし、simple-acmeはWindows用にはいい感じ。自分はまだansibleやZenworksなどを使わずに手作業で設定してるんだけど、罰を受けるのが好きだからっていうのもあるし、今のところはまだ小規模だからね。DNS-Persist-01は自分には必要ないと思うけど、明らかに誰かには必要みたい。