DNS CAAレコードとTLS証明書

# 概要

DNS CAAレコードとTLS証明書への影響についての備忘
作成日: 2025/3/29

# 目次
1. DNS CAAレコードについて
    1-1. DNS CAAレコードとは何か
    1-2. DNS CAAレコードの効果
    1-3. DNS CAAレコードの目的
2. DNS CAAレコードの事例
    2-1. DNS CAAレコードの書式
    2-2. issue属性
    2-3. issuewild属性
    2-4. iodef属性
3. DNS CAAレコード設定時の注意点
4. 現時点での主な設定例



# 1. DNS CAAレコードについて

## 1-1. DNS CAAレコードとは何か

- DNS CAAは、DNS Certification Authority Authorizationの略である
- CAAレコードは、有効なTLS証明書やS/MIME証明書(以下、証明書という)を発行するCAの範囲を規定し制限する

## 1-2. DNS CAAレコードの効果

- CAAレコードに特定のCAを設定すると、それ以外のCAがそのドメインに対して発行した証明書は無効となる
- 一方でCAAレコードがない場合、ほとんど大半のドメインがそうだが、その場合はそのドメインの証明書をどのCAが発行していても有効となる

## 1-3. DNS CAAレコードの目的

- 世界中の任意の証明書の発行サービスは、あらゆる任意のドメインに対する証明書を発行することができる
- 証明書の発行サービスは世界中の多くの企業が行なっており、そのすべてが厳格とまではいかずとも適切にそのドメインの正しい所有者に対してだけ証明書を発行するとは限らない
- したがって、故意または過失などによって、自社のドメインの証明書を、赤の他人がどこかで人知れず発行させて取得してしまうリスクというのは全く否定できるものではない
- DNS CAAレコードを設定することで、そのリスクを大幅に縮小することができる

# 2. DNS CAAレコードの事例

## 2-1. DNS CAAレコードの書式

CAAレコードは下記のように書く

- `flag`には、`0`から`255`までの数字(unsigned integer)を書くが、今のところ`0`で固定
- `tag`には、`issue` `issuewild` `iodef`などを書き、属性を示す
- `value`には、属性の値を書く

```text:
CAA <flags> <tag> <value>
```

## 2-2. issue属性

### 2-2-1. issue属性の機能

- issue属性は、そのドメインとサブドメインに対する証明書を発行できるCAを規定する

```shell-session:
# この場合、certs.example.orgとそのサブドメインは、"ca1.example.net"だけが証明書を発行できる
$ dig +noall +answer certs.example.org
certs.example.org. 86400 IN CAA 0 issue "ca1.example.net"
```

### 2-2-2. issue属性の複数設定

- issue属性は、複数設定することができ、その場合それらのCAはいずれも証明書を発行できる

```shell-session:
# この場合、certs.example.comとそのサブドメインは、"ca1.example.net"と"ca2.example.org"だけが証明書を発行できる
$ dig +noall +answer certs.example.com
certs.example.com. 86400 IN CAA 0 issue "ca1.example.net"
certs.example.com. 86400 IN CAA 0 issue "ca2.example.org"
```

### 2-2-3. 空のissue属性値設定

- issue属性に空のCAを指定した場合、そのドメインに対していかなるCAも証明書を発行できない

```shell-session:
# この場合、nocerts.example.comとそのサブドメインは、どのCAも証明書を発行できない
$ dig +noall +answer nocerts.example.com
nocerts.example.com. 86400 IN CAA 0 issue ";"
```

### 2-2-4. 文法的に誤った設定値

- issue属性に文法的に誤った値を指定した場合、空のCAを指定したものとみなされる

```shell-session:
# この場合、malformed.example.comとそのサブドメインは、どのCAも証明書を発行できない
$ dig +noall +answer malformed.example.com
malformed.example.com. 86400 IN CAA 0 issue "%%%%%"
```

### 2-2-5. 空の属性値を含む複数設定
- issue属性を複数設定し、そのうちの一つが空のCAを指定した場合は、それ以外のissue属性で設定されたCAは証明書を発行できる

```shell-session:
# この場合、certs2.example.comとそのサブドメインは、"ca1.example.net"だけが証明書を発行できる
$ dig +noall +answer certs2.example.com
certs2.example.com. 86400 IN CAA 0 issue "ca1.example.net"
certs2.example.com. 86400 IN CAA 0 issue ";"
```

### 2-2-6. issue属性の設定値の拡張

- issue属性の機能を拡張させるためにその値を拡張することができる

#### 2-2-6-1. 拡張「cansignhttpexchanges」

- 一部のCAではSXG(Signed HTTP Exchanges)拡張機能付きの証明書発行のために、DNS CAAレコードのissue属性に「cansignhttpexchanges」拡張の設定を要求している

```shell-session:
$ dig +noall +answer sxgcert.example.com
sxgcert.example.com. 86400 IN CAA 0 issue "ca1.example.net; cansignhttpexchanges=yes"
```

#### 2-2-6-2. 拡張「account」

- issue属性だけでは、そのCAに対して証明書を発行する利用者を制限することができないという限界は否めない。「account」拡張を付与することにより特定のアカウントに対してのみ証明書を発行できるようにするため、より厳格になる

```shell-session:
$ dig +noall +answer certs3.example.com
certs3.example.com. 86400 IN CAA 0 issue "ca1.example.net; account=beda0771d006aa3a6c11b05187d4"
```


## 2-3. issuewild属性

- issuewild属性は、ワイルドカード証明書のための属性で、それ以外はissue属性と同様である
- 通常はissue属性とissuewild属性とを揃えるのが、運用上平易で間違いも少ないだろう

### 2-3-1. issue属性のみの場合

- issue属性のみ設定された場合は、ワイルドカード証明書もissue属性の設定に従う
- 下記の場合は、"wild1.example.com"と"*.wild1.example.com"のいずれの証明書も"ca1.example.net"だけが発行できる

```shell-session:
$ dig +noall +answer wild1.example.com
wild1.example.com. 86400 IN CAA 0 issue "ca1.example.net"
```

#### 2-3-2. issuewild属性のみの場合

- issuewild属性のみ設定された場合、ワイルドカード証明書はissuewild属性の設定に従うが、一方で通常の証明書は何らの制限も受けない
- 下記の場合は、"*.wild2.example.com"の証明書は"ca1.example.net"だけが発行できるが、"www.wild2.example.com"のようなワイルドカードではない証明書はどこからでも発行できる

```shell-session:
$ dig +noall +answer wild2.example.com
wild2.example.com. 86400 IN CAA 0 issuewild "ca1.example.net"
```

#### 2-3-3. issue属性とissuewild属性のいずれも同じ設定値の場合

- issue属性とissuewild属性のいずれも設定され、双方とも同じ設定値の場合は、issue属性のみ設定した場合と同じになる

```shell-session:
$ dig +noall +answer wild3.example.com
wild3.example.com. 86400 IN CAA 0 issue "ca1.example.net"
wild3.example.com. 86400 IN CAA 0 issuewild "ca1.example.net"
```

#### 2-3-4. issue属性とissuewild属性とで別々の設定値となる場合

- issue属性とissuewild属性のいずれも設定され、それぞれが別の設定値となる場合は、それぞれがそれぞれの設定値に従う
- 下記の場合、"wild4.example.com"の証明書は"ca1.example.net"だけが発行できるが、一方で"*.wild4.example.com"の証明書は"ca2.example.com"だけが発行できる

```shell-session:
$ dig +noall +answer wild4.example.com
wild4.example.com. 86400 IN CAA 0 issue "ca1.example.net"
wild4.example.com. 86400 IN CAA 0 issuewild "ca2.example.com"
```

#### 2-3-5. issue属性とissuewild属性の両方の設定があり、issuewild属性は空の設定値の場合

- 下記の場合、"wild5.example.com"の証明書は"ca1.example.net"だけが発行できるが、一方で"*.wild5.example.com"の証明書はどのCAも発行できない

```shell-session:
$ dig +noall +answer wild5.example.com
wild5.example.com. 86400 IN CAA 0 issue "ca1.example.net"
wild5.example.com. 86400 IN CAA 0 issuewild ";"
```

#### 2-3-6. issue属性とissuewild属性の両方の設定があり、issue属性は空の設定値の場合

- 下記の場合、"wild6.example.com"の証明書はどのCAも発行できないが、一方で"*.wild6.example.com"の証明書は"ca2.example.com"だけが発行できる

```shell-session:
$ dig +noall +answer wild5.example.com
wild5.example.com. 86400 IN CAA 0 issue ";"
wild5.example.com. 86400 IN CAA 0 issuewild "ca2.example.com"
```

### 2-3-7. issuewild属性の設定値の拡張

- issuewild属性の設定値の拡張については、issue属性のそれと同様

## 2-4. iodef属性

- iodef属性は、DNS CAAレコードのissue属性やissuewild属性の規定に反するような証明書要求、あるいは証明書発行があった場合に、それを通知する手段を設定する

### 2-4-1. 電子メールによる通知

- iodef属性の設定値に"mailto:メールアドレス"が指定された場合、IODEF(The Incident Object Description Exchange Format, RFC7970)に従って電子メールの添付ファイルとして設定されたメールアドレスに通知される

### 2-4-2. HTTPSによる通知

- iodef属性の設定値にURL(http or https)が指定された場合、IODEFレポートが、Transport of Real-time Inter-network Defense (RID) Messages (RFC6546)の方式で設定されたURLに送られる
- 下記の設定では、このDNS CAAレコードに反した証明書要求または証明書発行についての通知は、電子メールまたはHTTPSのいずれか、もしくはその両方によって行われる

```shell-session:
$ dig +noall +answer report.example.com
report.example.com. 86400 IN CAA 0 issue "ca1.example.net"
report.example.com. 86400 IN CAA 0 iodef "mailto:security@example.com"
report.example.com. 86400 IN CAA 0 iodef "https://iodef.example.com/"
```

# 3. DNS CAAレコード設定時の注意点

- さあ、では我が社で管理するドメインにもCAAレコードを導入してみようじゃないか、という場合には気をつけなければならないことがある
- 例えば、「tokyo.example.com」と「osaka.example.com」のTLS証明書を別々の部署で管理しているのに、DNSの管理はすべて一括で管理しているというような場合には、事前にそれぞれの部署と調整して、DNS CAAレコードの設定を、「tokyo.example.com」と「osaka.example.com」のそれぞれに対して行うか、あるいは「example.com」に一括で双方の部署で使用しているTLS証明書の発行に支障のないように設定し、そしてその事情を連携しておくことが必要となる
- もし、TLS証明書の発行主体が組織の中で細分化しているような場合は、その辺りの管理は煩雑になるだろう

# 4. 現時点での主な設定例

- 2025年3月時点での代表的なドメインの設定例を見てみる

※念のため、メールアドレスについては一部伏せておく


## Google

```shell-session:
$ dig +noall +answer google.com caa     
google.com.		86400	IN	CAA	0 issue "pki.goog"
```

## Apple

```shell-session:
apple.com.		299	IN	CAA	0 issuewild "pki.apple.com"
apple.com.		299	IN	CAA	0 iodef "mailto:********@apple.com"
apple.com.		299	IN	CAA	0 issue "pki.apple.com"
```

## Meta

```shell-session:
$ dig +noall +answer meta.com caa 
meta.com.		3600	IN	CAA	0 issue "digicert.com; account=271b0beda0771d006aa3a6c11b05187d456d6c239b46cb5241196095b09c92af"
```

## Cloudflare


```shell-session:
$ dig +noall +answer cloudflare.com caa 
cloudflare.com.		300	IN	CAA	0 issue "pki.goog; cansignhttpexchanges=yes"
cloudflare.com.		300	IN	CAA	0 issue "ssl.com"
cloudflare.com.		300	IN	CAA	0 issuewild "comodoca.com"
cloudflare.com.		300	IN	CAA	0 issuewild "digicert.com; cansignhttpexchanges=yes"
cloudflare.com.		300	IN	CAA	0 issuewild "letsencrypt.org"
cloudflare.com.		300	IN	CAA	0 issuewild "pki.goog; cansignhttpexchanges=yes"
cloudflare.com.		300	IN	CAA	0 issuewild "ssl.com"
cloudflare.com.		300	IN	CAA	0 iodef "mailto:********@cloudflare.com"
cloudflare.com.		300	IN	CAA	0 issue "comodoca.com"
cloudflare.com.		300	IN	CAA	0 issue "digicert.com; cansignhttpexchanges=yes"
cloudflare.com.		300	IN	CAA	0 issue "letsencrypt.org"
```

# フッター

## 仲間を募集しています！

ARIではエンジニア・ITコンサルタント・PM職全方位で仲間を募集しております。
カジュアル面談、随時受付中です！
ご興味ある方はこちらをご覧ください。

https://note.com/ari_hr/n/n4aed9ba75421