こんにちは、アーキテクトのやまぱんです。
補足コメントや質問、いいね、拡散、是非お願いします🥺!
間違ってたら優しく教えてください!
今回は Azure で学ぶ CNAME をテーマにしています。
Azure で CNAME と言えば、Private Endpoint ですね!!
TL;DR
- CNAME の名前解決について Azure で、具体的にいうと Private Endpoint を題材に理解する
- 名前解決で CNAME が返って来た時、クライアントまでかえってくるのか? が気になったので検証
- Azure Private Endpoint の名前解決では CNAME チェーンはクライアントに返らず、最終的な A レコードのみ返却される
以下ブログ内で書かれている部分に関してすこし気になったのが背景
https://dev.classmethod.jp/articles/route53-resolverdnsfirewall-cname/
今回のポンチ絵
VNet の DNS は DNS サーバー ME-ID DS 10.3.0.5 / 10.3.0.4 を指定してる。
なので、デフォルトでは Client → ME-ID DS → 168.63.129.16 へ DNS クエリを送信する構成。
検証ポイント
登場人物は多いですが、要するに Client VM (vm-client-2019) から Private Endpoint を 設定した PaaS (今回は API Management:apim-te.azure-api.net) の名前解決について、名前解決の時に CNAME が返って来た時、クライアントまでかえってくるのか?を考えます。
前提知識
-
ME-ID DS :
Microsoft Entra ID Domain Services。オンプレ AD 不要で Azure 上にマネージドなドメインコントローラ機能を提供。今回は ME-ID DS から 168.63.129.16 にフォワーダー設定を入れている。 -
Private Endpoint :
Azure の PaaS リソースへ VNet 経由でプライベート IP でアクセスできる仕組み。サービスをインターネットに公開せず安全に利用できる。閉域化とは切り離せない。 -
168.63.129.16 :
Azure 内部で使われる特殊な仮想IP (VIP)。DNS、DHCP、Health probe などの基盤通信に利用。Azure VMからは常にこのIPが見える。対象 VNet のプライベート DNS ゾーン の名前解決が可能。
168.63.129.16はAzureの基盤通信に必須で、DNS 解決の最終処理を担うため今回の検証のキーとなる IP です。 -
APIM :
Azure API Management。APIの公開・認証・スロットリング・監視などを統合管理するPaaSサービス。内外のアプリケーション間のAPIゲートウェイとして機能。 -
Google DNS :
Google Public DNS (8.8.8.8 / 8.8.4.4)。無料で利用できる大規模再帰 DNS サービス。
高速・信頼性の高い名前解決を提供。 -
閉域化 :
インターネットを経由せず、専用線やVPNなどの閉じたネットワーク内で通信すること。セキュリティや遅延の安定性を重視した設計で用いられる。Private IP での通信が可能。 -
Private IP :
RFC1918で定義された、内部ネットワーク専用のIPアドレス。直接インターネットには出られない。
例: 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 (家庭LANの「192.168.1.x」が典型例)。 -
Global IP :
インターネットに直接到達可能な一意のIPアドレス。外部公開用のリソースで利用される。
例: 8.8.8.8(Google DNS)、13.78.106.99(Azure Public IP)など。 -
Resolve-DnsName :
Windows PowerShell のコマンドレット。A/AAAAレコードを同時に問い合わせ、詳細な結果を返す。 -Type パラメータでレコード種類を指定可能で、NRPTやOSのDNS設定を反映する。(今回の環境ではスクリプトrdn で aliasを設定している。PowerShell スクリプト こちら) -
Add-DnsClientNrptRule :
Windows の NRPT (Name Resolution Policy Table) に新しいルールを追加するコマンド。
特定のドメイン名空間に対して使用する DNS サーバや暗号化設定を指定できる。
今回は Client 端末に DNS フォワーダー のような設定を入れるために利用。
参考:Windows Client OS で条件付きフォワーダー的なことをやってみる -
Get-DnsClientNrptPolicy :
現在クライアントに適用されている NRPT のポリシーを一覧表示するコマンド。
Add/Remove したルールが正しく反映されているかの確認に使う。 -
nslookup :
古くからあるDNS確認ツール。基本は再帰問い合わせで、対話モードや「set norecurse」で非再帰も可能。 OSの DNS クライアントを通さず独自に問い合わせるため、NRPTなどのポリシーは無視することがある。
<参考>
Resolve-DnsName と nslookup の違いについては以下に書いていますのでよろしければどうぞ!
PowerShell に alias を設定する方法も記載しています。
Private Endpoint の名前解決について
Private Endpoint が設定された FQDN の名前解決について簡単に以下の動作となる。
-
プライベート DNS ゾーンの名前解決ができるとき → Private IP が返却される
FQDN (apim-te.azure-api.net) の名前解決 → CNAME (apim-te.privatelink.azure-api.net) チェーン解決 → Aレコード返却 → Private IP
apim-te.azure-api.net(下の例と同じ FQDN 、Private IP(10.2.0.6) が返ってきている)

-
プライベート DNS ゾーンの名前解決ができないとき → Global IP が返却される
FQDN (apim-te.azure-api.net) の名前解決 → CNAME (apim-te.privatelink.azure-api.net) チェーン解決 → Aレコード返却 → Global IP
apim-te.azure-api.net(上の例と同じ FQDN 、Global IP(13.79.106.99) が返ってきている)

・ privatelink CNAME としてapim-te.privatelink.azure-api.netが解決されている。
※なお、Private Endpoint が設定されていない PaaS の FQDN の名前解決に関しては privatelink CNAME が設定さず privatelink CNAME が返ってこずに Global IP が返される挙動となる。
つまり、Private Endpoint を設定すると、privatelink CNAME チェーンが挿入されて、その CNAME の解決結果に応じて Private IP を返すようになる(プライベート DNS ゾーンの名前解決ができるとき)。
検証🔥
-
※ rdn で aliasを設定している -
nslookupはDnsClientNrptRuleの影響を受けないので使わない -
-DnsOnlyでキャッシュの影響を無視。
Phase 1 - 前提確認
まずクライアント側で以下それぞれ確認。
-
Private Endpoint の名前解決ができること
rdn apim-te.azure-api.net -DnsOnly

・ privatelink CNAME としてapim-te.privatelink.azure-api.netが解決され、Private IP10.2.0.6が返却されている。 -
Private Endpoint の名前解決ができること 2
rdn apim-te.privatelink.azure-api.net -DnsOnly

privatelink CNAME の場合も Private IP10.2.0.6が返却されている。 -
Google DNS で Global IP が返ってくること
rdn apim-te.azure-api.net -Server 8.8.8.8 -DnsOnly

はい、こちらもGlobal IP が返ってきている。
Phase 2 - DnsClientNrptRule の設定 と その確認
Add-DnsClientNrptRule -Namespace ".privatelink.azure-api.net" -NameServers 8.8.8.8
.privatelink.azure-api.net ドメインへの名前解決は、既定のDNSではなく 8.8.8.8 に問い合わせるというポリシーを追加している。(クライアントでのフォワーダー設定)
Phase 3 - 今回のメイン🚀🚀
ではここで、以下の 2つのコマンドでどのような IP アドレスが返されるかを確認したい。
rdn apim-te.privatelink.azure-api.net -DnsOnlyrdn apim-te.azure-api.net -DnsOnly
まず、rdn apim-te.privatelink.azure-api.net -DnsOnly🔥
想定通り、コマンド実行時にパブリック DNS (8.8.8.8) を指定せずに、privatelink CNAME が解決されて、Global IP(13.78.106.99) が返ってきていることがわかる。
「Private Endpoint の名前解決ができること 2」 で試した時は Private IP が返却されていたが、DnsClientNrptRule の設定により Global IP が返却されていることがわかる
つぎに、rdn apim-te.azure-api.net -DnsOnly 🔥🔥
ここで改めて整理しましょう。
<状況>
DNSフォワーダーとして .privatelink.azure-api.net を Google DNS 8.8.8.8を設定している。この状況でrdn apim-te.azure-api.net -DnsOnlyを実施するとどうなる??
<前提(再掲)>
- プライベート DNS ゾーンの名前解決ができるとき
FQDN (apim-te.azure-api.net) の名前解決 → CNAME (apim-te.privatelink.azure-api.net) チェーン解決 → Aレコード返却 → Private IP
<仮説>
- クライアントに一度 CNAME が返却され、クライアントから privatelink の CNAME クエリがされるなら...
→ Global IP(13.78.106.99) が返ってくる - 一方で、クライアントには最終解決結果だけが返却され、反復問い合わせや CNAME チェーンの解決はフルリゾルバ (168.63.129.16) 側で処理されている のなら...
→ クライアントは直接 Global IP を得ることはなく、Private IP (10.2.0.6) が返ってくる
- 結果

結論からいうと、Private IP Private IP (10.2.0.6) が返ってくる
つまり、クライアントは最終結果 (A レコードの Private IP) だけを受け取り、CNAME 自体は中継的に見えない。つまり「CNAME がクライアントに見えてから再度問い合わせる」挙動にはならない。
おまけ:パケットキャプチャ
Phase 3 の状況でそれぞれコマンドのパケットのキャプチャです。
フィルタ udp port 53 or tcp port 53
余談ですが、今回のようにレコードを指定していない場合は A レコード と AAAA レコード を問い合わせをしてることがわかる。黄色ハイライト部分が A レコードの問い合わせ。
A レコードの問い合わせも、AAAA レコードも 一度の問い合わせと応答で返って来ていることがわかる。
rdn apim-te.azure-api.net -DnsOnly

rdn apim-te.azure-api.net -DnsOnly -server 8.8.8.8
おまけ: dig +trace
今回の検証は Windows の Resolve-DnsName を使った「再帰問合せ」が前提でした。
再帰問合せではフルリゾルバ(例: 168.63.129.16)が CNAME チェーンを処理して、クライアントには最終的な A レコードだけが返却されます。
そのため、クライアントは途中でどんな CNAME が返ってきているかを意識できません。
一方で、dig +trace のように 反復問合せ(iterative query) を行うと、ルートサーバから権威サーバまで順に問い合わせを行うため、CNAME を含む「解決の途中経路」を確認することができます。
例:
dig +trace apim-te.azure-api.net
このコマンドを実行すると、
- ルートサーバへの問い合わせ
- azure-api.net の権威サーバへの問い合わせ
- apim-te.azure-api.net が CNAME で apim-te.privatelink.azure-api.net を指していること
- さらにその CNAME をたどって最終的な A レコードが返却されるまでの流れ
といった一連の解決経路が表示されます。
つまり:
- 再帰問合せ → クライアントには「最終的な A レコード」だけが見える
- 反復問合せ(dig +trace) → クライアント側で「CNAME を含む解決経路」を可視化できる
今回のテーマである「CNAME がクライアントまで返ってくるか?」という問いに対して、通常の環境(再帰問合せ)では返ってこないが、dig +trace のような特殊な問い合わせ方法を使えば途中の CNAME を観察できる、という整理になります。
以下が CNAME を確認できていることの例です。
Windows で digコマンドを使う方法
公式から Windows 向けのリリースは止まっているのでアーカイブしました。(自己責任でお願いします)
まとめ
- Azure の Private Endpoint を設定した FQDN では、名前解決時に privatelink ドメインの CNAME が自動的に挿入される。(通常のクライアントからの問い合わせは
再帰問合せであり、その場合を想定)- 例:
apim-te.azure-api.net→ CNAME →apim-te.privatelink.azure-api.net→ A レコード解決
- 例:
- しかし、クライアント側に返却されるのは CNAME チェーンそのものではなく、最終的な A レコード結果のみ。
- つまり、CNAME を挟んだ名前解決における挙動としては、クライアントが CNAME を受け取って再度問い合わせる挙動にはならず、フルリゾルバ側(例: 168.63.129.16)が CNAME チェーンを処理して最終結果を返す。
- NRPT などで
.privatelink.azure-api.netの解決先を変更すると、CNAME に対して名前解決した場合は別の経路で解決され、結果的に異なる IP が返るケースもある。 - 検証結果から、通常の再帰問合せを行う名前解決フローにおいて、CNAME の存在はクライアントからは意識することはなく、クライアントからは最終解決結果(A レコード)が見えるだけであることが確認できた。







