2026年6月18日

2026年6月18日

DANE と CAA レコードを併用する設定|証明書の「発行」と「利用」の両方を DNS で縛り、更新や認証局の変更で止めない

CAA レコードと DANE(TLSA レコード)は、どちらも DNS に置いて証明書を管理する仕組みですが、効く場面が違います。CAA は「どの認証局がこのドメインの証明書を発行してよいか」を認証局に伝え、発行のときに確かめられます。DANE は「このサーバーが接続時に出す鍵はこれ」と接続相手に伝え、通信のたびに確かめられます。両方を置くと、ほかの認証局による誤発行を防ぎつつ、メールサーバーへの接続では鍵そのものを固定できます。この記事では、メールサーバー(SMTP)で両者を組み合わせる設定と、証明書の更新や認証局の変更で互いを壊さない順番を説明します。

DNSSEC と DANE の関係(署名が必要な範囲や、DNSSEC の作業で DANE を巻き込まない手順)は、別の記事で詳しく扱っています。ここでは CAA との組み合わせに絞ります。

CAA と DANE の役割の違い

CAA DANE(TLSA)
誰が確かめるか 証明書を発行する認証局 接続する側(DANE に対応した送信メールサーバーなど)
いつ確かめるか 証明書の発行・更新のとき 接続のたび
守るもの 許可していない認証局による発行 偽の証明書を出すサーバーへの接続
DNSSEC なくても使えるが、署名があれば改ざんに強くなる 必要

CAA は、すでに発行された証明書には影響しません。また、CAA を守らない認証局や、攻撃者が別の経路で手に入れた証明書を、接続する側が見分ける仕組みでもありません。そこを補うのが DANE です。逆に DANE は、Web ブラウザーの HTTPS では使われておらず(2026年10月現在)、実際に効くのは主に SMTP です。Web サイトの証明書については、CAA と証明書の透明性(CT)ログの監視が主な守りになります。

前提を確かめる

  • ゾーンが DNSSEC で署名されている。 DANE には必須です。CAA にとっても、署名があれば応答の改ざんを防げます。署名が壊れて検証に失敗すると、多くの認証局は CAA を確かめられないとして発行を止めるため、更新が通らなくなる点にも注意します。
  • DNS 事業者が CAA と TLSA を登録できる。 どちらか一方しか扱えないサービスもあります。
  • 今の証明書の発行元が分かっている。 次のコマンドで確かめます。
# 今の証明書の発行者と期限(受信メールサーバー)
openssl s_client -connect mx1.example.com:25 -starttls smtp -servername mx1.example.com \
  </dev/null 2>/dev/null | openssl x509 -noout -issuer -dates

# 今の CAA(なければ何も返らない)
dig +short CAA example.com
dig +short CAA mx1.example.com

CAA は、証明書の名前(ここでは mx1.example.com)から始めて、レコードが見つかるまで親のドメインへさかのぼって探されます。mx1.example.com 自体に CAA がなければ example.com の CAA が使われ、mx1.example.com に CAA を置けば、そちらが優先されます。サブドメインに古い CAA が残っていて、親の設定を変えても効かない、という失敗がよくあります。

手順1:CAA を書く

Let's Encrypt で証明書を取っている場合の例です。

example.com. 3600 IN CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456789; validationmethods=dns-01"
example.com. 3600 IN CAA 0 issuewild ";"
example.com. 3600 IN CAA 0 iodef "mailto:security@example.com"

1行目は、Let's Encrypt だけに発行を許します。accounturi を付けると、自分の ACME アカウントからの申請に限られ、同じ認証局をほかの人が使って発行することも防げます。validationmethods は、ドメイン所有の確認方法を限定します。どちらも RFC 8657 で定められた拡張で、Let's Encrypt は対応していますが、認証局によっては対応していないため、使う認証局の文書で確かめます。2行目はワイルドカード証明書の発行をすべて禁止し、3行目は規則に反した申請があったときの連絡先です(連絡を送るかどうかは認証局次第です)。

アカウント URI の値(例の 123456789 の部分)は、certbot ならアカウント情報から確かめられます。新しめの certbot には certbot show_account というサブコマンドがあり、表示される URI をそのまま使います。値を間違えると次回の更新が拒否されるので、最初は accounturi と validationmethods を付けずに公開し、更新が通ることを確かめてから絞り込む進め方が安全です。

手順2:TLSA を公開する

受信メールサーバーの公開鍵から TLSA の値を作ります。CAA と組み合わせる場合も、推奨されるのは「3 1 1」(DANE-EE、公開鍵、SHA-256)です。

openssl x509 -in /etc/letsencrypt/live/mx1.example.com/cert.pem -noout -pubkey \
  | openssl pkey -pubin -outform DER \
  | openssl dgst -sha256 | awk '{print $NF}'
_25._tcp.mx1.example.com. 3600 IN TLSA 3 1 1 (上で得た16進文字列)

「3 1 1」は認証局を問わずに鍵だけを見るため、認証局を変えても、鍵が同じなら TLSA は変わりません。一方、「2 1 1」(DANE-TA)で中間証明書の鍵を指定する方法もありますが、Let's Encrypt のように中間証明書が定期的に切り替わる認証局では、切り替えのたびに TLSA が合わなくなるおそれがあるため、運用の手間が増えます。

手順3:証明書の更新で両方を保つ

更新のたびに、CAA は認証局によって、TLSA は接続相手によって確かめられます。どちらも壊さないための要点は2つです。

  • 鍵を変えずに更新する。 certbot では、証明書の設定に鍵の再利用を指定しておくと(--reuse-key)、更新後も公開鍵が変わらず、TLSA を触らずに済みます。
  • 確認方法を CAA と合わせる。 validationmethods=dns-01 と書いたのに、更新が http-01 で行われる設定のままだと、更新が CAA で拒否されます。certbot の更新設定(/etc/letsencrypt/renewal/ の設定ファイル)に記録された認証方式と、CAA の指定が一致しているかを確かめます。

更新を自動化している場合は、更新後にメールサーバーへ新しい証明書を読み込ませる処理(certbot の deploy フックで Postfix を再読み込みするなど)も含めておきます。

手順4:認証局を変えるときの順番

CAA を置いている状態で認証局を変えるには CAA の書き換えが要り、TLSA は鍵を変えるかどうかで対応が変わります。次の順番で進めると、途中で発行も配送も止まりません。

  1. CAA に新しい認証局を追加する(古い認証局の行は残す)
  2. CAA の TTL が切れるのを待ってから、新しい認証局で証明書を取る
  3. 鍵を変えた場合は、新しい鍵の TLSA を古い TLSA と並べて公開し、TLSA の TTL 分待つ
  4. メールサーバーの証明書を新しいものに差し替え、外から確かめる
  5. 古い TLSA を削除する
  6. 古い認証局での更新が不要になったことを確かめてから、CAA から古い認証局の行を外す

鍵を変えずに認証局だけ変える場合、3 と 5 は不要です。作業の前には、DNS のゾーンの内容をエクスポートするなどして控えておき、すぐ戻せるようにします。

確認のコマンド

# CAA と TLSA が署名つきで返るか(ad フラグを見る)
dig @1.1.1.1 +dnssec CAA example.com | grep -E 'flags:|status:'
dig @1.1.1.1 +dnssec TLSA _25._tcp.mx1.example.com | grep -E 'flags:|status:'

# サーバーの証明書と TLSA が一致するか
openssl s_client -connect mx1.example.com:25 -starttls smtp -servername mx1.example.com \
  -dane_tlsa_domain mx1.example.com \
  -dane_tlsa_rrdata "3 1 1 (TLSA の16進文字列)" </dev/null 2>/dev/null \
  | grep -E 'Verification|DANE'

あわせて、CT ログの検索サービスで自分のドメインに発行された証明書を定期的に見ておくと、CAA をすり抜けた発行があった場合に気づけます。

よくあるつまずき

  • 更新が CAA で拒否される。 サブドメイン側に古い CAA が残っている、accounturi の値が別アカウントのもの、validationmethods と実際の認証方式が違う、の順に疑います。認証局のエラーメッセージに CAA の語が含まれていれば、まずこの3点です。
  • 更新後に DANE 対応の送信側からメールが届かない。 鍵が変わったのに TLSA を更新していない状態です。openssl s_client で照合し、鍵を再利用する設定になっているかを確かめます。
  • CAA の変更が反映されない。 認証局側でも CAA の結果を一定時間保持することがあります。TTL を確かめ、時間を置いて再試行します。

まとめ

  • CAA は発行のときに認証局が、DANE は接続のたびに相手が確かめます。両方を置くと、誤発行の防止と接続時の鍵の固定を組み合わせられます。
  • CAA は accounturi と validationmethods で自分のアカウントと認証方式に絞れます。ただし最初は付けずに更新を確かめてから絞ります。
  • TLSA は「3 1 1」にし、証明書の更新では鍵を再利用すると、CAA の更新と TLSA が互いに干渉しにくくなります。
  • 認証局を変えるときは、CAA に追加、発行、TLSA を並べて公開、差し替え、古い TLSA と古い CAA の削除、の順に進めます。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲