Cloudflare/IBM Cloud Internet Service(CIS)におけるCNAME Flatteningの挙動

#1. はじめに

IBM Cloud Internet Service(CIS)では、トップレベルドメイン（＝CISに登録したドメイン=ゾーンAPEX）に対して、CNAME Flatteningが有効化されている。本記事では、その必要性と挙動を実際のコマンドを使って確認する。

簡単なまとめ

- flattening=展開するという意味。
- 通常CNAMEが登録されている場合、権威DNSはCNAMEに登録されているFQDNをクライアントに返す。クライアントは再度そのFQDNに対して名前解決を行う。
- CNAME Flatteningが有効化されている場合、権威DNSが代わりにCNAMEに登録されているFQDNに対して名前解決をして（flatteningして）、クライアントにIPアドレスを返す。

#2. CNAME Flatteningの必要性
なぜCNAME Flatteningが必要かというと、[RFC1912](https://tools.ietf.org/html/rfc1912)によって、CNAMEは同一名の他レコードと同居できないという制限があるからである。

>   A CNAME record is not allowed to coexist with any other data.  In
   other words, if suzy.podunk.xx is an alias for sue.podunk.xx, you
   can't also have an MX record for suzy.podunk.edu, or an A record, or
   even a TXT record.  Especially do not try to combine CNAMEs and NS
   records like this!:

これは、例えば

```txt:NGケース。Aレコードとの同居
certest.tk in A     1.2.3.4
certest.tk in CNAME www.example.com

```

とか

```txt:NGケース。NSレコードとの同居
certest.tk in NS    nsxxx.name.cloud.ibm.com
certest.tk in CNAME www.example.com
```

などのように構成できないということを意味している。DNSであるドメイン（この例だと`certest.tk`）を管理しようとした場合、上位のドメインから委任を受ける上で必ずそのドメインに対するNSレコードを委任される側のDNSにも設定する必要があるので、このままでは`certest.tk`に対してCNAMEは追加できないことになる。（**逆にいうと、すでにNSレコードが存在していた場合は、同一名のCNAMEをクライアントに返してはいけないというのが権威DNSの仕様である**）。
**逆に言うと、クライアントからの要求にCNAMEを返さないように振る舞えばいいのである。CNAME Flatteningが有効化されていることで、権威DNS設定画面上では`certest.tk `に対するCNAMEを登録しているかのように扱うことができるが、実際は権威DNSがCNAMEで定義されたFQDNの名前解決を実施しそのIPアドレスをクライアントに応答するため、クライアントから見たらあたかも`certest.tk`に対するAレコードが登録されているかのように権威DNSは振る舞うことができる。**これにより、通常他のレコードと同居できないというCNAMEの制約を権威DNSの振る舞いで回避することできる。

#3. CNAME Flatteningなしの例（いわゆる一般のDNS問い合わせ）

CISでcertest.tkというトップレベルドメインを利用していたとする。この場合、以下のCNAMEが登録されていた場合、DNSへの問い合わせは以下のようになる。

<img width="1043" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/6486d19e-f04e-a0a0-df7e-a6f24682aaec.png">

```txt:CNAME
test.certest.tk in CNAME www.example.com
```

```txt:CNAME_Flatteningなし
1) クライアント  --->   test.certest.tkを探索   --->  権威DNS
2) クライアント  <---   www.example.comを返す   <---  権威DNS
3) クライアント  --->   www.example.comを探索   --->  権威DNS
4) クライアント  <--- Aレコード（IPアドレス）を返す <---  権威DNS
```

```shell-session:通常のCNAMEレコードの名前解決（Proxyなし）。CNAMEの応答あり。

# dig CNAME +noall +answer @1.1.1.1 test1.certest.tk
test1.certest.tk.	300	IN	CNAME	www.example.com.

# dig A +noall +answer @1.1.1.1 test1.certest.tk
test1.certest.tk.	289	IN	CNAME	www.example.com.
www.example.com.	9122	IN	A	93.184.216.34
```

（参考）CISのCNAMEレコードにてproxyを有効機能を有効化した場合は、すべてのrequestはCISのEdgeに送られるので、Aレコード（CISのEdgeのIPアドレス）が返ってきている。

```shell-session:通常のCNAMEレコードの名前解決（Proxyあり）。
# dig CNAME +noall +answer @1.1.1.1 www4.certest.tk
（回答なし）

# dig A +noall +answer @1.1.1.1 www4.certest.tk
www4.certest.tk.	250	IN	A	104.18.18.234
www4.certest.tk.	250	IN	A	104.18.19.234
```

#4. CNAME Flatteningありの例（ゾーンAPEXの場合）

CISで`certest.tk`というトップレベルドメイン(ゾーンAPEX)を利用していたとする。この場合、以下のCNAMEが登録されていた場合、DNSへの問い合わせは以下のようになる。

<img width="1043" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/6486d19e-f04e-a0a0-df7e-a6f24682aaec.png">


```txt:CNAME
certest.tk in CNAME www.example.com
```

```txt:CNAME_Flatteningあり（権威DNSが名前解決をしてくれている）
1) クライアント      ---> certest.tkを探索 --->      権威DNS
2)                                                権威DNS ---> www.example.comの名前解決
3) クライアント <--- Aレコード(IPアドレス）を返す  <--- 権威DNS
```

```shell-session:トップレベルドメインのCNAMEの名前解決（Proxyなし）。CNAMEに対する応答がない。あたかもAレコードが登録されているかのように振る舞う。
# dig CNAME +noall +answer @1.1.1.1 certest.tk
（回答なし）

# dig A +noall +answer @1.1.1.1 certest.tk
certest.tk.		299	IN	A	93.184.216.34
```

（参考）CISのCNAMEレコードにてproxyを有効機能を有効化した場合は、すべてのrequestはCISのEdgeに送られるので、Aレコード（CISのEdgeのIPアドレス）が返ってきている。

```shell-session:トップレベルドメインのCNAMEの名前解決（Proxyあり）
# dig CNAME +noall +answer certest.tk
（回答なし）

# dig A +noall +answer certest.tk
certest.tk.		289	IN	A	104.18.18.234
certest.tk.		289	IN	A	104.18.19.234
```



#5. （参考）CNAME Flatteningの参考情報

- https://cloud.ibm.com/docs/infrastructure/cis?topic=cis-dns-concepts&locale=en#dns-concepts-root-record-cname-flattening
- https://blog.cloudflare.com/introducing-cname-flattening-rfc-compliant-cnames-at-a-domains-root/
- https://support.cloudflare.com/hc/en-us/articles/200169056-CNAME-Flattening-RFC-compliant-support-for-CNAME-at-the-root