0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudflareのCNAME FlatteningがDNSの仕様に反さずに成立する理由

0
Last updated at Posted at 2026-08-18

example.com のようなapexにCNAMEは置けません。これはDNSの仕様上の制約です。ところがCloudflareの管理画面では、apexにCNAMEを設定できます。設定できるだけでなく、実際に動作します。Cloudflare自身は、この機能をこう説明しています。

Cloudflare finds the IP address that a CNAME points to... Cloudflare then returns the final IP address instead of a CNAME record.

CloudflareはCNAMEが指すIPアドレスを見つけ、CNAMEレコードの代わりに、最終的なIPアドレスを返す。

(Cloudflare Docs - CNAME flattening)

この説明は正確です。ただし、これだけでは次が分かりません。

  • 変換の主体はどこか
  • いつ変換されるのか
  • 変換した結果、なぜ仕様違反にならないのか
  • Aレコードを直接書いた場合との、同じ点と違う点

DNSの仕様を明示的に示したうえで、そこから順に導きます。

本記事が前提とするDNSの仕様

以降で使う仕様を先に示します。いずれもRFCに書かれた内容で、ここでは真であるものとして扱います。本文からは「前提1」のように参照します。

前提1. 問い合わせは名前と型の組で行われる

DNSの問い合わせは、名前だけでは成立しません。example.com の何を知りたいのか、という型を必ず伴います。A を問い合わせればIPv4アドレスを、MX を問い合わせればメールサーバーを探します。

この2つには仕様上の呼び名が付いており、以降の引用にも出てきます。問い合わせている名前をQNAME、問い合わせている型をQTYPEと呼びます。example.comA を引く場合、QNAMEが example.com、QTYPEが A です。

前提2. 権威サーバーが応答へ入れる内容は仕様で決まっている

RFC 1034の4.3.2節は、権威サーバーの動作を手順として定義しています。問い合わせ名がゾーン内のノードに一致したときの処理が、次の記述です。

If the data at the node is a CNAME, and QTYPE doesn't match CNAME, copy the CNAME RR into the answer section of the response, change QNAME to the canonical name in the CNAME RR, and go back to step 1.

Otherwise, copy all RRs which match QTYPE into the answer section and go to step 6.

そのノードのデータがCNAMEであり、QTYPEがCNAMEと一致しない場合は、CNAME RRを応答のanswerセクションへ複写する。そしてQNAMEをそのCNAME RRのcanonical nameへ変更し、手順1へ戻る。

そうでない場合は、QTYPEに一致するすべてのRRをanswerセクションへ複写し、手順6へ進む。

この仕様が定めているのは、応答のanswerセクションの中身です。事業者が内部でどのようなデータ構造を持つかは規定していません。この区別は後で使います。

前提3. CNAMEがある名前には他のデータを置けない

RFC 1034の3.6.2節にこう書かれています。

If a CNAME RR is present at a node, no other data should be present; this ensures that the data for a canonical name and its aliases cannot be different.

あるノードにCNAME RRが存在する場合、他のデータを置くべきではない。これにより、canonical nameとその別名でデータが異なる事態を防げる。

原文は should で、絶対的な禁止としては書かれていません。この規則を確定させたのがRFC 2181の10.1節で、DNS上のどの名前についても次のいずれか1つだけが成り立つ、と整理しました。

+ CNAMEレコードが1つだけ存在する (DNSSEC利用時はSIG・NXT・KEYを伴ってよい)
+ 1つ以上のレコードが存在し、そのどれもCNAMEではない
+ 名前は存在するが、レコードを持たない
+ 名前が存在しない

以降で「前提3」と書くときは、この確定した形を指します。

前提4. SOAとNSはすべてのゾーンで必須で、originに置かれる

RFC 2181の6.1節にこう書かれています。

The authoritative servers for a zone are enumerated in the NS records for the origin of the zone, which, along with a Start of Authority (SOA) record are the mandatory records in every zone.

あるゾーンの権威サーバーは、そのゾーンのoriginに置かれたNSレコードによって列挙される。NSレコードはSOAレコードとともに、すべてのゾーンにおいて必須のレコードである。

ここに出てくる2つのレコードにも役割があります。SOA (Start of Authority) は、そのゾーンの管理情報を持つレコードです。更新の通し番号やキャッシュの既定値などが入ります。NS (Name Server) は、そのゾーンを担当するネームサーバーを示すレコードです。

originとは、ゾーンの最上位の名前です。example.com ゾーンのoriginは example.com そのもので、これをapexと呼びます。

apexにCNAMEを置けない理由

前提3と前提4を重ねます。

前提4より、example.com ゾーンのapex (= example.com) には
SOAとNSが存在する。

前提3より、CNAMEがある名前には他のデータを置けない。

apexにCNAMEを置いたとすると、そのapexにはCNAMEとSOAとNSが
同居することになる。

これは前提3に反する。

したがって、apexにCNAMEを置くことはできない。

ゾーンファイルで見ると次の状態です。

$ORIGIN example.com.
@   IN  SOA   ns1.example.com. admin.example.com. ( ... )   ← 前提4により必須
@   IN  NS    ns1.example.com.                              ← 前提4により必須
@   IN  CNAME customer.cdn-provider.example.                ← 前提3に反する

これはCloudflareやFastlyが設けた制限ではなく、仕様から導かれる結論です。

サブドメインでCNAMEを使ったときの動作

apexではない名前には、前提4が適用されません。www.example.com はゾーンのoriginではないため、SOAとNSを持ちません。したがってCNAMEを単独で置けます。

このとき何が起きるかを、省略せずに追います。ゾーンは2つ登場します。

【顧客のゾーン】 example.com
@     IN  SOA   ns1.example.com. ...
@     IN  NS    ns1.example.com.
www   IN  CNAME customer.cdn-provider.example.

【CDN事業者のゾーン】 cdn-provider.example
@          IN  SOA   ns1.cdn-provider.example. ...
@          IN  NS    ns1.cdn-provider.example.
customer   IN  A     198.51.100.20

利用者が https://www.example.com を開いたときの流れです。

[1] リゾルバー → example.com の権威サーバー
    「www.example.com の A をください」(前提1)

[2] 権威サーバーの判断
    ノード www.example.com のデータはCNAMEである。
    QTYPE は A で、CNAME と一致しない。
    → 前提2の前半にあたる。
    → CNAME RR を answer に入れ、QNAME を
      customer.cdn-provider.example へ差し替える。

[3] リゾルバーが受け取る応答
    www.example.com.  CNAME  customer.cdn-provider.example.

[4] リゾルバー → cdn-provider.example の権威サーバー
    「customer.cdn-provider.example の A をください」

[5] 権威サーバーの判断
    ノードのデータは A で、QTYPE と一致する。
    → 前提2の後半にあたる。
    → A RR を answer に入れる。

[6] リゾルバーが受け取る応答
    customer.cdn-provider.example.  A  198.51.100.20

[7] リゾルバー → 利用者
    198.51.100.20

この流れには、2つの性質が現れています。

1つ目は、IPアドレスの値を保持しているのはCDN事業者のゾーンであることです。顧客のゾーンには customer.cdn-provider.example という名前しか書かれていません。CDN事業者が手順[5]で返す値を変えれば、顧客は何もしなくても新しいIPアドレスへ切り替わります。

2つ目は、リゾルバーが2つの権威サーバーへ問い合わせていることです。手順[1]と手順[4]がそれにあたります。CNAMEを使うと、往復が1回増えます。

apexにAレコードを直接書いたときの動作

前節のとおり、apexではCNAMEを使えません。残る選択肢はAレコードです。

【顧客のゾーン】 example.com
@   IN  SOA   ns1.example.com. ...
@   IN  NS    ns1.example.com.
@   IN  A     198.51.100.20

流れは短くなります。

[1] リゾルバー → example.com の権威サーバー
    「example.com の A をください」

[2] 権威サーバーの判断
    ノードのデータは A で、QTYPE と一致する。
    → 前提2の後半にあたる。
    → A RR を answer に入れる。

[3] リゾルバーが受け取る応答
    example.com.  A  198.51.100.20

[4] リゾルバー → 利用者
    198.51.100.20

往復は1回で済みます。しかし、サブドメインの場合に確認した1つ目の性質が失われています。

IPアドレスの値を保持しているのが顧客のゾーンになりました。 CDN事業者がこの値を変えたくても、書き換える権限は顧客だけが持ちます。1000社の顧客がいれば、1000社への依頼が必要になります。

ここまでで問題が明確になります。apexでは、次の2つを同時に満たせません。

(a) 前提3と前提4に反しないこと
(b) IPアドレスの値をCDN事業者側で変更できること

前提3が禁じている対象の範囲

前提3をもう一度読みます。

If a CNAME RR is present at a node, no other data should be present; this ensures that the data for a canonical name and its aliases cannot be different.

あるノードにCNAME RRが存在する場合、他のデータを置くべきではない。これにより、canonical nameとその別名でデータが異なる事態を防げる。

禁じられているのは、あるノードにCNAMEと他のデータを共存させることです。これはゾーンのデータについての規定です。

一方、前提2が定めているのは、answerセクションに何を入れるかでした。

そして、リゾルバーが観測できるのはanswerセクションの中身だけです。相手のゾーンファイルの中身を見ることはできません。ここから次が導けます。

リゾルバーが観測するのは、返ってきた応答だけである。

前提3の違反は、CNAMEと他のデータが同じノードに共存している
という、ゾーン側の状態である。

権威サーバーが応答のanswerセクションにCNAMEを一切入れなければ、
リゾルバーはCNAMEの存在を観測しない。

したがって「apexにCNAMEを置く」ことと、
「apexへの問い合わせにCNAMEで答える」ことは、別の事柄である。

言い換えると、apexで禁止されているのはCNAMEを答えとして返すことであり、CNAMEに相当する設定を事業者が内部で持つことではありません。仕様は事業者の内部データ構造を規定していないからです。

CNAME Flatteningは、この差を使います。

CNAME Flatteningの手順

Cloudflareの管理画面でapexにCNAMEを設定したとき、実際に何が起きるかを追います。

【顧客がCloudflareに設定する内容】
example.com   CNAME   customer.cdn-provider.example

この設定はCloudflare内部のものであり、DNSのワイヤ上に流れるCNAME RRではありません。前節のとおり、仕様が制約するのは応答の中身です。

利用者が https://example.com を開いたときの流れです。

[1] リゾルバー → Cloudflareの権威サーバー
    「example.com の A をください」

[2] Cloudflareの権威サーバーの判断
    設定上、example.com の行き先は
    customer.cdn-provider.example である。
    しかし、この名前をCNAMEとして答えることはできない。
    → 自分でこの名前を解決しにいく。

[3] Cloudflare → cdn-provider.example の権威サーバー
    「customer.cdn-provider.example の A をください」

[4] Cloudflareが受け取る応答
    customer.cdn-provider.example.  A  198.51.100.20

[5] Cloudflareがリゾルバーへ返す応答
    example.com.  A  198.51.100.20
                  ↑
              名前は example.com のまま。
              answerセクションにCNAMEは入っていない。

[6] リゾルバー → 利用者
    198.51.100.20

手順[5]が結論です。応答の形は、前提2の後半「QTYPEに一致するRRをanswerセクションへ複写する」に一致しています。CNAMEは答えに含まれていないため、前提3の違反はリゾルバーから観測されません。

Cloudflareの説明も同じ内容です。

Cloudflare finds the IP address that a CNAME points to... Cloudflare then returns the final IP address instead of a CNAME record.

CloudflareはCNAMEが指すIPアドレスを見つけ、CNAMEレコードの代わりに、最終的なIPアドレスを返す。

この論証が及ぶ範囲

ここまでの論証は、A/AAAAの問い合わせに限った話です。実際のapexには、メール用のMXや、所有権確認用のTXTが独立して置かれます。

example.com  A    198.51.100.20         ← 設定した行き先を解決して合成する
example.com  MX   10 mail.example.net   ← ゾーンのデータをそのまま返す
example.com  TXT  "v=spf1 ..."          ← 同上

真のCNAMEであれば、どの型を問い合わせても別名の先へ解決されます。CNAME Flatteningの動作はこれと違います。A/AAAAだけを合成し、他の型についてはゾーンのデータを返します。型ごとに振る舞いが違うため、前提3の4状態のどれにも厳密には当てはまらない状態になります。

仕様に反していないと言えるのは、応答のanswerセクションにCNAMEが現れないからであって、この名前が真のCNAMEとして振る舞っているからではありません。

Aレコード直書きとの比較

Aレコード直書きの場合とCNAME Flatteningの場合を並べます。リゾルバーが受け取る応答は、どちらも同じ形です。

Aレコード直書き                CNAME Flattening

example.com. A 198.51.100.20   example.com. A 198.51.100.20

区別が付きません。ここが「分かったような、分からないような」気持ちになる箇所です。応答が同じなら、何が違うのか。

違うのは、その値をいつ、誰が決めたかです。

Aレコード直書き CNAME Flattening
値が決まる時点 顧客が設定した時点 問い合わせを受けた時点
値を保持している場所 顧客のゾーン CDN事業者のゾーン
値を変更できる主体 顧客 CDN事業者
名前を解決する主体 (解決は発生しない) Cloudflareの権威サーバー
リゾルバーの往復 1回 1回

サブドメインでCNAMEを使う場合の利点、つまり「値をCDN事業者側で変更できる」という性質が、apexでも成立しています。しかもリゾルバーの往復は増えていません。サブドメインでは2往復でしたが、Flatteningでは追加の名前解決をCloudflare自身が引き受けるため、リゾルバーから見た往復は1回のままです。

つまりCNAME Flatteningは、Aレコード直書きの応答の形と、CNAMEの運用上の性質を、同時に成立させています。

成立の条件

この方式が成り立つには条件があります。前節の手順[2]と手順[3]の実行主体が、Cloudflareの権威サーバーだからです。

顧客のゾーンをCloudflareが権威として管理していること。 手順[3]で名前を解決する主体は、apexへの問い合わせを受ける権威サーバーです。顧客が別のDNS事業者を使っている場合、Cloudflareにはそもそも問い合わせが届きません。

Cloudflare側の適用範囲は次のとおりです。

CNAME flattening occurs by default for all plans when your domain uses a CNAME record for its zone apex.

ドメインがzone apexにCNAMEレコードを使っている場合、CNAME flatteningはすべてのプランで既定で行われる。

apex以外のCNAMEもflattenする設定は、有料プラン向けの選択肢として提供されています。またCloudflareのプロキシを通すレコードについては、次のように書かれています。

Proxied records are flattened by default as they return Cloudflare anycast IPs.

プロキシされたレコードは、Cloudflareのanycast IPを返すため、既定でflattenされる。

この方式で対処できないこと

行き先が解決できない場合。 手順[3]で名前が解決できなければ、返せるIPアドレスがありません。Cloudflareはこの場合、空の応答 (NODATA) を返すと説明しています。CNAMEを返す方式であれば、リゾルバー側で「行き先が引けない」と分かりますが、Flatteningではその情報が失われます。

顧客がDNS事業者を選べない場合。 これが最も大きい制約です。SaaSのカスタムドメインでは、顧客のDNS事業者はそれぞれ違います。「Cloudflareへゾーンを移してください」と全顧客に依頼できるとは限りません。企業によっては、DNSの移管そのものが社内規定で許可されていない場合もあります。

つまりCNAME Flatteningが使えるのは、DNS事業者を自分で決められる場合に限られます。

まとめ

導出を並べ直します。

前提3 (CNAMEは他データと共存不可)
前提4 (apexにはSOAとNSが必須)
        ↓
apexにCNAMEを置けない
        ↓
apexはAレコードで受けるしかない
→ 値を変更できるのは顧客だけになる
        ↓
前提3が禁じているのはゾーン側の共存であり、
リゾルバーが観測するのは応答だけ
        ↓
応答にCNAMEを入れずにAだけを返せば、
前提3の違反は発生しない
→ 行き先の解決は権威サーバーが自分で行う
        ↓
結果: 応答の形はAレコード直書きと同じ。
      しかし値を決めているのはCDN事業者側。

「CNAMEをAレコードに変換して返す」という一文が指していたのは、CNAME Flatteningの手順[2]から手順[5]です。変換しているのはCloudflareの権威サーバーで、変換のタイミングは問い合わせを受けたときです。仕様違反にならないのは、変換の結果として応答からCNAMEが消えるからです。

そして、この方式は顧客のDNS事業者をCloudflareにできる場合にだけ成立します。それができない場合は、DNSの層ではなくネットワークの層で入口を用意することになります。apexへ直接書けるIPアドレスを事業者側が持ち、そのアドレスの届く先を経路制御で切り替える方式です。前の記事で扱ったAnycast静的IPアドレスがこれにあたります。

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?