要約

  • CNAME は一つのowner nameを、ただ一つのtargetへ向かうaliasにする。aliasと到着先が矛盾した答えを出さないよう、ownerはA、MX、TXT、NSなど通常のデータを併有できない。
  • resolverはCNAMEをcacheし、targetで検索を再開する。source zoneは迂回を、target側のauthorityは最終データを制御する。これはdelegationでも、identityやservice availabilityの証明でもない。

一つの名前に二つの役割を持たせると何が壊れるか

portal.exampleをservice.example.netへのCNAMEとして公開したとする。addressを尋ねられたsource serverはaliasを返し、resolverはtargetでAまたはAAAAを探す。ところがsource zoneが同時にportal.example自身のA recordも持っていたら、cacheはどちらを信じればよいのか。旧名に直結したaddressか、aliasをたどって得たaddressか。

1987年11月のRFC 1034は、その競合を実装ごとの好みに委ねなかった。CNAMEのownerはaliasであり、RDATAに書かれたdomain nameがcanonical targetである。あるnodeにCNAMEがあれば、通常の別データを置いてはならない。

これはzone fileを美しくする作法ではない。仕様は理由を二つ示した。canonical nameとaliasのデータが食い違ってはならない。そしてCNAMEをcacheしたresolverは、同じownerに別typeの反証がないかsource authorityへ問い合わせ直すことなく、その迂回を使えなければならない。

排他性が生んだauthorityは小さい。CNAMEはaddressやmail exchangerを決めない。次の質問をどの名前から始めるかだけを決める。

答えが次の質問を書き換える

CNAMEは同義語を静的に返すrecordではない。QTYPEがCNAME以外なら、RFC 1034のalgorithmはCNAME RRをAnswerへ入れ、処理中のQNAMEをtargetへ変更し、検索を最初からやり直す。CNAMEそのものを問う場合だけ追跡しない。依頼者が見たいのは迂回路そのものだからである。

RFC 9499の用語は、この移動を明確にする。original QNAMEはQuestionに実際に送った名前、effective QNAMEはCNAME chainの途中で実際に解決した名前、final QNAMEは末尾の名前である。responseがoriginal questionをそのままechoしていても、要求に答えるRRsetのownerは別の名前になり得る。

終点で失敗したとき、この区別は決定的になる。source aliasは存在し、そのauthorityが正しく応答していても、targetは存在しない、故障している、あるいは別zoneに属しているかもしれない。final QNAMEのnegative answerは、original aliasが存在しない証明にはならない。

迂回はdelegationではない

aliasとdelegationはどちらもresolverを先へ進ませるが、移すものが異なる。zone cutのNS RRsetは、descendant zoneのauthorityを持つname serverを示す。CNAMEはsource authorityが自分の名前について公開したdataであり、別lookupを開始させるだけでsource zoneをtarget operatorへ渡さない。

source側はportal.exampleを作成、変更、削除し、alias TTLを決める。service.example.netのauthorityはtargetのA、AAAAなどと各TTLを制御する。sourceがtargetを指したからといってtargetを書き換える権限を得ず、target側もsource aliasを編集できない。

RFC 6604は後にCNAME/DNAME chainのstatusを整理した。最初のaliasにauthoritativeなanswerを返しながら、後段についてreferralやfailureを含むresponseはあり得る。最初の発言に対するauthorityは、旅程全体へのauthorityではない。

一つのaliasに一つのtarget――一台のhostに一つの名前ではない

“canonical”という語は、各hostやinterfaceに公式名が一つしかないかのような誤解を招いた。RFC 2181は、その推論を否定する。DNSにhost identity全体を一名へ制限する規則はない。

規則はもっと狭い。一つのCNAME ownerにはcanonical targetが一つだけある。またownerを口語で「CNAME」と呼ぶと方向が隠れる。ownerはaliasで、record valueがこのalias操作におけるcanonical nameである。

複数のdomain nameが同じserviceへ導くことはできる。aliasでない名前なら複数種類の通常RRsetも持てる。禁止されるのは、一つのownerが「別の場所で問い直せ」と宣言しながら、自分も独立したdestinationとして答えることである。

zone apexがこの近道を使えない理由

zone apexにはSOAとNSが必要である。CNAME ownerはそれらの通常dataと共存できない。したがってapexを通常のCNAMEにすることはできない。

RFC 1912は、魅力的に見える誤設定の危険を記録した。当時のBINDを例に、apexのNSとCNAMEを並べるとserverがCNAMEを採用して他のresourceを無視し、配下の名前まで見えなくなる場合を示す。挙動の細部は当時のimplementationに属するが、data model上の競合は同じである。

現在のserviceがapexでaddress answerを合成したりflatteningを提供したりすることはある。そのproduct behaviorは有用でも、wire上のCNAME RRとは別物である。すべてを“apex CNAME”と呼ぶと、障害時に確認すべきauthorityとcacheの境界が見えなくなる。

aliasを置けないtarget positionがある

RFC 2181は、NSのtargetとMXのexchangeにaliasを使ってはならないとも定める。NS/MX queryでは、serverが関連addressをAdditional sectionへ添えて余分なqueryを減らせる。しかしその処理はCNAMEを追跡し、canonical targetのaddressまで補ってくれない。

aliasを埋め込めばqueryと負荷が増え、delegationのような厳しい場面ではaddress不足がresolution failureにつながる。NSやMXを書くadministratorはaliasを一度解決し、address RRsetを直接所有する名前を公開すべきである。

これは「名前から名前へ」の全面禁止ではない。予測可能なaddress discoveryに依存する位置で、暗黙の追加hopを許さない規則である。

DNSSECはproofを加えたが、第二のdestinationを戻さなかった

DNSSECの発展に伴い、“no other data”には重要な例外が入った。RFC 2181は当時のsecurity recordを認め、RFC 4034はsigned zoneのCNAME ownerにRRSIGとNSECを要求した。

それらはtargetと競合するdataではない。RRSIGはCNAME RRsetをauthenticateし、NSECはauthenticated denialとtype evidenceを支える。alias nodeの状態を証明しても、その名前に独自のaddress、mail route、application payloadを与えない。

RFC 4033が示すsecurity boundaryも狭い。DNSSECはvalidation成功時にdata origin authentication、integrity、authenticated denialを提供する。target applicationのidentity、service health、契約相手、source nameの法的ownershipは証明しない。

chainは許容され、loopは検出される

aliasが別のaliasを指すことはできる。RFC 1034は効率のためmultiple levelを避けるよう勧めるが、有限chainそのものをerrorとはしない。resolverが捕捉すべきなのはloopと、最終的に存在しない名前へ着く場合である。

運用対象は文字列置換ではなくgraphになる。各edgeにowner、authority、TTL、場合によってDNSSEC stateがあり、terminal RRsetには別のTTLがある。cacheごとに旧edgeの失効時刻が違うため、一つの移行が観測点ごとに別段階に見える。

それがdecouplingの利益と価格である。source operatorはtarget dataを複製せず親しまれた名前を動かせる。target operatorは全alias zoneを編集せずaddressを変えられる。しかし両者は独立して変化し、過去のstatementはTTLまでcacheに残る。

混在する真実を拒んだから薄い共通層が保たれた

CNAMEは、分散管理の問題を意図的に小さなprimitiveで解いた。等価名を登録するglobal registryも、どのaddressがaliasに“本当に属する”かを裁く中央機関も要らない。どのresolverでもcacheして追跡できる、曖昧でない一つのedgeだけでよい。

排他規則こそ設計の中心である。source nameは迂回路かdestinationのどちらかになれるが、両方にはなれない。迂回を選んだときのauthorityは本物だが狭い。一つのtargetを公開し、chainのevidenceを保ち、destination dataはdestinationのcontrolに残す。

情報源と証拠の限界

原型とresolution algorithmはRFC 1034、RFC 1035、operational errorとnaming clarificationはRFC 1912、RFC 2181、DNSSEC exceptionはRFC 4033、RFC 4034、chain statusと現行terminologyはRFC 6604、RFC 9499に基づく。これらはcurrent deployment share、provider固有のflattening、resolver chain limit、dangling aliasの頻度、application ownership、現在のservice availabilityを証明しない。