2026年6月16日

2026年6月16日

CAAレコードの検証手順:証明書の発行が止まる前に確認すること

CAA レコードの検証は、「証明書を発行したいホスト名から親ドメインへ順にたどり、最初に見つかった CAA が使う CA を許可しているか」を確かめる作業です。この記事では、dig での確認方法、CA が実際に行う判定の順序、Let's Encrypt の事前テスト、発行を拒否されたときの原因の切り分けまでを説明します。CAA を新しく追加したときや、証明書の更新が「CAA」を理由に失敗したときに使ってください。

CAA レコードの役割と判定のしくみ

CAA(Certification Authority Authorization、RFC 8659)は、「このドメインの証明書を発行してよい CA」を DNS で宣言するレコードです。公的な証明書を発行する CA には、発行前に CAA を確認することが業界の基準(CA/Browser Forum の Baseline Requirements)で求められています。ブラウザが閲覧時に CAA を確認するわけではなく、効くのは発行・更新のときだけです。

CA の判定は次の順で進みます。

  1. 証明書に入れるホスト名(例: www.example.com)の CAA を問い合わせる
  2. CAA が無ければ親(example.com)、さらにその親へとさかのぼる
  3. 最初に見つかった CAA の集合だけを使い、そこで判定する
  4. どの階層にも CAA が無ければ、どの CA でも発行できる

ポイントは3番目です。www.example.com に CAA を1つでも置くと、example.com の CAA は参照されなくなります。サブドメインにだけ別の CA を許可したつもりが、親の設定と食い違って更新が止まる、という事故はここから起きます。

手順1: 対象のホスト名ごとに CAA を確認する

まず、証明書に含めるすべてのホスト名で CAA を確認します。

dig +short www.example.com CAA
dig +short example.com CAA

応答の例は次のようになります。

0 issue "letsencrypt.org"
0 issuewild ";"
0 iodef "mailto:security@example.com"

それぞれの意味は以下のとおりです。

  • issue: 通常の(ワイルドカードでない)証明書を発行してよい CA
  • issuewild: ワイルドカード証明書を発行してよい CA。これがあると、ワイルドカードについては issue より優先される
  • iodef: 規則に反する発行要求があった場合の連絡先(CA が対応するかは CA 次第)
  • 値が ";" の場合は「どの CA にも許可しない」という意味

上の例では、*.example.com のワイルドカード証明書は Let's Encrypt でも発行できません。ワイルドカードを使うなら issuewild "letsencrypt.org" に変えるか、issuewild の行を削除して issue の設定に従わせます。

親ドメインまで含めて一度に確かめたい場合は、次のように上位へたどるループが便利です。

name=www.sub.example.com
while [ -n "$name" ]; do
  echo "== $name"
  dig +short "$name" CAA
  case "$name" in *.*) name=${name#*.} ;; *) name= ;; esac
done

最初に何か表示された階層が、CA が実際に使う CAA です。

手順2: 権威サーバーの値と DNSSEC を確認する

DNS の管理画面で変更した直後は、キャッシュの影響で古い値が見えることがあります。ドメインの権威ネームサーバーに直接問い合わせると、現在の設定値を確かめられます。

dig +short example.com NS
dig @ns1.example-dns.net example.com CAA

ns1.example-dns.net の部分は、1行目で表示されたネームサーバーに置き換えてください。権威サーバーの値が正しく、手元のリゾルバだけ古い場合は、TTL の経過を待てば反映されます。

もう一つ見落としやすいのが DNSSEC です。ゾーンで DNSSEC を有効にしていて署名が壊れていると、CA 側の CAA 問い合わせが失敗し、CAA の内容にかかわらず発行が拒否されることがあります。検証を行うリゾルバに問い合わせて、status: SERVFAIL にならないかを確認します。

dig example.com CAA @1.1.1.1

SERVFAIL が返る場合は、CAA ではなく DNSSEC(DS レコードと DNSKEY の不一致など)を先に直す必要があります。

手順3: CA 名の書き方を確認する

issue に書く値は、CA ごとに決められた識別子です。Let's Encrypt は letsencrypt.org、Google Trust Services は pki.goog のように、CA の公式ドキュメントに記載されています。証明書を買ったブランド名と、実際に発行する CA の識別子が異なる場合もあるため、推測で書かず、CA や証明書の販売元の案内を確認してください。ここで挙げた識別子は(2026年10月現在)のもので、CA の統合などで変わることがあります。

CDN やマネージド証明書を使っている場合は特に注意が必要です。CDN が裏側で別の CA から証明書を取得していると、自分で書いた CAA がその CA を許可しておらず、更新に失敗することがあります。Cloudflare のように、CAA を設定するとサービスが使う CA のレコードを自動で補う事業者もありますが、扱いはサービスごとに異なるので、各社のドキュメントで確認してください。

Let's Encrypt では、RFC 8657 の拡張により accounturi(特定の ACME アカウントに限定)や validationmethods(認証方法の限定)も指定できます。

example.com. 3600 IN CAA 0 issue "letsencrypt.org; validationmethods=dns-01"

制限を強くするほど、認証方法を変えたときに発行できなくなるため、運用手順とあわせて決めてください。

手順4: 本番の発行前にテストする

CAA を変更したら、本番の証明書を更新する前に、テスト環境で発行できるかを試します。certbot の場合、--dry-run を付けると Let's Encrypt のステージング環境で更新処理を試せます。

sudo certbot renew --dry-run

ステージング環境も本番と同じく CAA を確認するため、ここで失敗すれば本番でも失敗します。CAA が原因の場合は、エラーメッセージに CAA レコードが発行を妨げている旨が表示されます。

発行を拒否されたときの切り分け

CAA が理由で発行に失敗した場合は、可能性の高い順に次を確認します。

  1. 許可している CA 名が違う: issue の値と、実際に発行する CA の識別子を照合する
  2. **ワイルドカードが issuewild で止められている**: ワイルドカードを含む証明書なら issuewild の行を確認する
  3. サブドメインの CAA が親の設定を上書きしている: 手順1のループで、最初に見つかる階層を確認する
  4. DNSSEC の不備で問い合わせが失敗している: 検証リゾルバで SERVFAIL にならないかを確認する
  5. 変更がまだ反映されていない: 権威サーバーに直接問い合わせ、TTL の経過を待つ

なお、flags を 128(critical)にして CA が知らないタグを書くと、CA は発行を拒否します。特別な理由がなければ 0 のままにしておきます。

まとめ

  • CA は証明書のホスト名から親へさかのぼり、最初に見つかった CAA だけで判定する
  • issue は通常の証明書、issuewild はワイルドカード用。";" はすべての CA を拒否する意味になる
  • 権威サーバーへの直接問い合わせで設定値を、検証リゾルバへの問い合わせで DNSSEC の不備がないかを確認する
  • CA の識別子は公式の案内で確認し、CDN やマネージド証明書が使う CA も許可に含める
  • 変更後は certbot renew --dry-run などで本番前に発行を試す

お気軽にご相談ください

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