AzureのPrivate DNSゾーンを設定する方法|VNet内の名前解決をazコマンドで構成する

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Azure > AzureのPrivate DNSゾーンを設定する方法|VNet内の名前解決をazコマンドで構成する
「AzureでLinux VMを複数台立ち上げたら、IPアドレスではなくホスト名でサーバー同士を呼び合いたい。でもデフォルトのDNSでは解決できない」
この状況に直面したことがあるエンジニアは多いはずです。AzureのデフォルトDNSはVNet内の自動名前解決をある程度サポートしますが、カスタムドメイン名や複数VNetにまたがる構成になると途端に限界を迎えます。さらに、VPN GatewayやExpressRouteでオンプレミスと接続済みの環境では「オンプレ側からAzureのドメインが引けない」「Azure VMから社内ドメインが解決できない」という別の壁にもぶつかります。

この記事では、azure private dns ゾーンの作成からVNetへのリンク、AレコードのCLI追加、オートレジストレーションによるVM自動登録まで、azコマンドを使って実際に構成する手順を解説します。さらに、オンプレとAzureのDNSを双方向に統合するDNS Private Resolverの構築手順、BlobストレージなどのPrivate Endpointと組み合わせた privatelink.* ゾーンの構成パターン、サービス別の --group-id パラメータと対応ゾーン名の一覧も取り上げます。Rocky Linux 9 / Ubuntu 24.04 LTSで動作確認済みです。

この記事のポイント

・azure private dns zoneはVNet専用の非公開ゾーンで外部から参照できない
・az network private-dns zone create でゾーン作成、vnet linkでVNetに接続する
・オートレジストレーションを有効にするとVM作成時にAレコードが自動登録される
・オンプレとAzureのDNSを双方向に統合するにはDNS Private Resolverを使う(VM不要)
・DNS Private ResolverのInbound/Outbound Endpointはそれぞれ専用サブネット(/28以上)が必要
・VNetサービスエンドポイントと異なり、Private EndpointはPaaS側にプライベートIPを割り当てる
・Private Endpoint専用サブネットは --disable-private-endpoint-network-policies true の設定が必要
・Private Endpoint のDNS統合には privatelink.* ゾーン + DNSゾーングループの両方が必要
・サービスごとに --group-id(blob/file/sqlServer/vault等)と privatelink.* ゾーン名が異なる
・nslookupでプライベートIPが返り、curlで403が返ることで閉域通信の確立を確認できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

AzureのPrivate DNSゾーンとは — VNet内専用の名前解決を担う仕組み

Azure Private DNSゾーンは、VNet内部だけで有効な完全非公開のDNSゾーンです。AWSでいうRoute 53のPrivate Hosted Zoneに相当します。標準のAzureパブリックDNSとは完全に独立しており、VNetにリンクしたサブスクリプション外からは参照できません。

主な特徴を整理します。

・外部から参照不可:インターネット上のDNSサーバーから解決できない
・VNet単位でリンク:1つのゾーンを複数のVNetに紐づけることが可能
・オートレジストレーション:VMを作成・削除するとAレコードが自動で更新される
・カスタムドメイン名:「corp.internal」など任意のドメイン名を使える
・Private Endpointとの連携:BlobストレージやKey Vault等のPaaSをPrivate Endpointで閉域化する際も Private DNS Zone(privatelink.*)を使う

ただし、AzureのVNetには「Azure Provided DNS」(IPアドレス:168.63.129.16)が組み込まれており、これはVNet内で完結する仕組みです。Private DNSゾーンをVNetにリンクすれば同一VNet内の名前解決は問題なく動きますが、VPN GatewayやExpressRouteで接続したオンプレミスとの境界を越えたDNSフォワーディングはそのままでは実現できません。オンプレのDNSサーバーからAzureのPrivate DNSゾーンに問い合わせを転送したい、またはAzure VMからオンプレの社内ドメインを解決したい場合は、後述の「DNS Private Resolver」が必要になります。

ここで、Azureには似た概念の「Service Endpoint」があります。Service EndpointはVNetからPaaSへのアクセスをAzureバックボーン経由にしますが、PaaS側のIPアドレスはパブリックIPのままです。一方、Private EndpointはPaaSのサブネット内NICにプライベートIPを割り当てるため、インターネットを完全に遮断した閉域通信を実現します。本記事で扱う Private DNS Zone は、主にこの Private Endpoint と組み合わせて使われます。新規構成では Private Endpoint を選択するのが Azureのベストプラクティスです。

AWSとの比較を表にまとめます。

比較軸 Azure Private DNS AWS Route 53 Private Hosted Zone
VNとの紐づけ VNet Link(az CLIで設定) VPC Association
自動登録 オートレジストレーション(オプション) なし(手動またはLambda連携)
コスト ゾーン/月 + クエリ課金 ゾーン/月 + クエリ課金
デフォルトDNSとの併用 Azureデフォルト(168.63.129.16)と共存 Route 53 Resolver と共存
Private Endpointとの連携 privatelink.* ゾーン + DNSゾーングループで自動登録 Interface Endpoint + Route 53 PHZ
ハイブリッドDNS統合 DNS Private Resolver(Inbound/Outbound Endpoint) Route 53 Resolver(Inbound/Outbound Endpoint)

AzureのデフォルトDNS(168.63.129.16)は同一VNet内の基本的な名前解決を提供しますが、カスタムドメイン名の付与や複数VNetをまたぐ構成には対応していません。その場合にPrivate DNSゾーンが必要になります。

用途によってゾーン名の命名規則が変わります。VM間の名前解決には「corp.internal」「prod.local」のような任意のドメイン名を使います。一方、BlobストレージやSQL DatabaseなどのPaaSをPrivate Endpointで閉域化する場合は、Azureが定めた「privatelink.blob.core.windows.net」のような privatelink.* ゾーン名が必要です。

作業環境と事前準備(Azureサブスクリプション・az CLI)

以下の環境で動作確認しています。

・Azureサブスクリプション:有効なサブスクリプション(無料試用版でも可)
・az CLIバージョン:2.50以上(az --version で確認)
・操作PC:Rocky Linux 9 または Ubuntu 24.04 LTS

az CLIのインストールは以下のコマンドで行います(Ubuntu/Debian系の場合)。

# az CLIのインストール(Ubuntu/Debian系) curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash # バージョン確認 az --version # Azureアカウントへのログイン az login

ログインするとブラウザが起動してAzureアカウントの認証を求めます。サーバー環境でブラウザが使えない場合は az login --use-device-code を使用してください。

リソースグループとVNetを準備する(前提構成)

Private DNSゾーンを設定するには、先にリソースグループとVNetが存在している必要があります。すでに構築済みの場合はこのセクションをスキップしてください。

# 変数を定義しておく RG="rg-dns-lab" LOCATION="japaneast" VNET="vnet-main" SUBNET="subnet-private" PE_SUBNET="subnet-pe" # リソースグループの作成 az group create --name $RG --location $LOCATION # VNetとVM用サブネットの作成 az network vnet create \ --resource-group $RG \ --name $VNET \ --address-prefix 10.0.0.0/16 \ --subnet-name $SUBNET \ --subnet-prefix 10.0.1.0/24 # Private Endpoint専用サブネットを追加する(VM用と分離するとNSG管理が楽になる) # --disable-private-endpoint-network-policies true が必須。省略すると作成時にエラーになる az network vnet subnet create \ --resource-group $RG \ --vnet-name $VNET \ --name $PE_SUBNET \ --address-prefixes 10.0.2.0/24 \ --disable-private-endpoint-network-policies true # 実行結果(抜粋) # "provisioningState": "Succeeded"

実行すると provisioningState: "Succeeded" の出力が返ります。--disable-private-endpoint-network-policies true はPrivate Endpoint専用サブネットに必須の設定です。省略すると、後述の az network private-endpoint create 実行時に「PrivateEndpointNetworkPoliciesEnable」エラーが発生します。既存のサブネットに後から追加する場合は az network vnet subnet update で変更できます。オンプレミスとAzureのDNS設定の違いを把握しておくと理解が深まります。Linuxのオンプレ側のDNS設定については「Linux DNS 設定の基本」を参照してください。

Private DNSゾーンを作成してVNetにリンクする

ここが本記事のコアとなる手順です。ゾーン名は「corp.internal」として進めます。

1. Private DNSゾーンを作成する

# Private DNSゾーンの作成(ゾーン名はカスタムドメイン名) az network private-dns zone create \ --resource-group $RG \ --name "corp.internal" # 実行結果(抜粋) # { # "location": "global", # "name": "corp.internal", # "provisioningState": "Succeeded" # }

ゾーン名には「.internal」や「.corp」のようなTLDが使われることが多いです。「.local」はmDNS(Bonjour)と競合するため、AzureのPrivate DNSゾーン名としては避けることが推奨されます。

2. VNetにリンクする

ゾーンを作成しただけではVMからは参照できません。VNetにリンクする手順が必要です。

# VNetリンクを作成(オートレジストレーションは後で有効化する) az network private-dns link vnet create \ --resource-group $RG \ --zone-name "corp.internal" \ --name "link-vnet-main" \ --virtual-network $VNET \ --registration-enabled false # リンク状態の確認 az network private-dns link vnet list \ --resource-group $RG \ --zone-name "corp.internal" \ --output table # 期待する出力 # Name ProvisioningState VirtualNetworkLinkState # link-vnet-main Succeeded Completed

VirtualNetworkLinkState が Completed になればリンク完了です。InProgress の場合はしばらく待ってから再確認してください。リンクが Completed になるまで数分かかることがあります。

AレコードをCLIで追加してLinux VMから名前解決を確認する

1. Aレコードを手動で追加する

# vmapp01.corp.internal → 10.0.1.4 を登録する例 az network private-dns record-set a add-record \ --resource-group $RG \ --zone-name "corp.internal" \ --record-set-name "vmapp01" \ --ipv4-address "10.0.1.4"

TTL(Time To Live)はデフォルトで3600秒(1時間)が設定されます。VMのIPアドレスが頻繁に変わる環境では --ttl 300 のように短くすることを検討してください。

2. 登録されたレコードを確認する

# ゾーン内の全レコードを一覧表示 az network private-dns record-set list \ --resource-group $RG \ --zone-name "corp.internal" \ --output table # 出力例 # Name Type Ttl # vmapp01 A 3600

3. Linux VMからdigコマンドで名前解決を確認する

同一VNet内のLinux VMにSSH接続して確認します。

# DNSクエリツールのインストール(Rocky Linux 9の場合) sudo dnf install -y bind-utils # Ubuntu 24.04 LTSの場合 sudo apt-get install -y dnsutils # digで名前解決を確認 dig vmapp01.corp.internal # 出力例(正常時) # ;; ANSWER SECTION: # vmapp01.corp.internal. 3600 IN A 10.0.1.4 # nslookupでの確認 nslookup vmapp01.corp.internal # Server: 168.63.129.16 # Address: 168.63.129.16#53 # # Name: vmapp01.corp.internal # Address: 10.0.1.4

ANSWER SECTION に A 10.0.1.4 が返ってくれば成功です。dig コマンドの詳しい使い方は「dig コマンドで DNS を調べる」を参照してください。

オートレジストレーションでVMのホスト名を自動登録する

毎回手動でAレコードを追加するのは運用負荷が高くなります。VNetリンクの --registration-enabled を true に設定すると、VM作成時に自動でAレコードが追加されます。

1. 既存VNetリンクのオートレジストレーションを有効化する

# updateコマンドでオートレジストレーションを有効化 az network private-dns link vnet update \ --resource-group $RG \ --zone-name "corp.internal" \ --name "link-vnet-main" \ --registration-enabled true

2. テスト用VMを作成して自動登録を確認する

# テスト用VMを作成(Rocky Linux 9ベースのRHELイメージ使用) az vm create \ --resource-group $RG \ --name vmtest02 \ --image RedHat:RHEL:9-lvm-gen2:latest \ --vnet-name $VNET \ --subnet $SUBNET \ --admin-username azureuser \ --generate-ssh-keys \ --public-ip-sku Standard # VM作成後にAレコードを確認 az network private-dns record-set list \ --resource-group $RG \ --zone-name "corp.internal" \ --output table # vmtest02.corp.internalのAレコードが自動登録されているはず # Name Type Ttl # vmapp01 A 3600 # vmtest02 A 10

VM作成後、vmtest02.corp.internal というAレコードが自動で追加されているはずです。VMを削除するとAレコードも自動で消えます。オートレジストレーションで登録されたAレコードのTTLは10秒(固定)です。

【注意】オートレジストレーションを使う場合、1つのVNetに対してオートレジストレーションが有効なゾーンは1つだけです。複数のPrivate DNSゾーンを同じVNetにリンクする場合、オートレジストレーションを有効化できるゾーンは1つに限られます。

オンプレとAzureのDNSを統合するDNS Private Resolver

VPN GatewayやExpressRouteでオンプレミスとAzureの疎通が取れているのに「オンプレのDNSサーバーからAzureのPrivate DNSゾーンに登録された名前が引けない」「Azure VMから社内ドメインが解決できない」——このDNSだけが境界を越えられないという問題は、ハイブリッド構成でよくぶつかる壁です。

かつてはVNet内にBINDやdnsmasqのVMを立ててフォワーダーにする方法が一般的でしたが、VM保守・HA・パッチ対応が運用負担になるという欠点がありました。2022年にGAとなったAzure DNS Private Resolverはこれをマネージドサービスに置き換えます。

DNS Private Resolverは1つのリソースで2種類のエンドポイントを持ちます。

・Inbound Endpoint:オンプレDNSサーバーからの問い合わせを受け付けるエントリポイント。専用サブネット内にプライベートIPが割り当てられ、このIPをオンプレDNSの条件付き転送先に設定する
・Outbound Endpoint + Forwardingルールセット:Azure VMからオンプレや外部DNSへ転送するための出口。ForwardingルールセットにDNSドメインと転送先DNSサーバーのIPを登録し、VNetにリンクすることでVNet内の全VMに転送ルールが適用される

InboundとOutboundの各エンドポイントにはそれぞれ専用サブネット(/28以上)が必要で、他のリソースと同居できないDelegated Subnetになります。

1. DNS Private Resolver用のサブネットを準備する

# Inbound Endpoint専用サブネット(他リソースと共存不可・/28以上が必須) az network vnet subnet create \ --resource-group $RG \ --vnet-name $VNET \ --name subnet-dns-inbound \ --address-prefix 10.0.3.0/28 # Outbound Endpoint専用サブネット az network vnet subnet create \ --resource-group $RG \ --vnet-name $VNET \ --name subnet-dns-outbound \ --address-prefix 10.0.4.0/28

2. DNS Private Resolverを作成する

VNET_ID=$(az network vnet show \ --resource-group $RG \ --name $VNET \ --query id -o tsv) az dns-resolver create \ --resource-group $RG \ --dns-resolver-name dns-resolver-hub \ --location $LOCATION \ --id "$VNET_ID" # 状態確認 az dns-resolver show \ --resource-group $RG \ --dns-resolver-name dns-resolver-hub \ --query provisioningState -o tsv # Succeeded

3. Inbound Endpointを作成する(オンプレ→Azure方向)

INBOUND_SUBNET_ID=$(az network vnet subnet show \ --resource-group $RG \ --vnet-name $VNET \ --name subnet-dns-inbound \ --query id -o tsv) az dns-resolver inbound-endpoint create \ --resource-group $RG \ --dns-resolver-name dns-resolver-hub \ --inbound-endpoint-name inbound-ep \ --location $LOCATION \ --ip-configurations private-ip-allocation-method=Dynamic id="$INBOUND_SUBNET_ID" # 割り当てられたIPアドレスを確認する az dns-resolver inbound-endpoint show \ --resource-group $RG \ --dns-resolver-name dns-resolver-hub \ --inbound-endpoint-name inbound-ep \ --query "ipConfigurations[0].privateIpAddress" -o tsv # 出力例: 10.0.3.4

表示されたIPアドレス(例:10.0.3.4)がオンプレDNSサーバーでの条件付き転送先になります。オンプレ側のBINDでは zone "corp.internal" { type forward; forwarders { 10.0.3.4; }; forward only; }; のように設定します。

4. Outbound EndpointとForwardingルールセットを作成する(Azure→オンプレ方向)

OUTBOUND_SUBNET_ID=$(az network vnet subnet show \ --resource-group $RG \ --vnet-name $VNET \ --name subnet-dns-outbound \ --query id -o tsv) # Outbound Endpoint作成 az dns-resolver outbound-endpoint create \ --resource-group $RG \ --dns-resolver-name dns-resolver-hub \ --outbound-endpoint-name outbound-ep \ --location $LOCATION \ --id "$OUTBOUND_SUBNET_ID" # Forwardingルールセット作成 OUTBOUND_EP_ID=$(az dns-resolver outbound-endpoint show \ --resource-group $RG \ --dns-resolver-name dns-resolver-hub \ --outbound-endpoint-name outbound-ep \ --query id -o tsv) az dns-resolver forwarding-ruleset create \ --resource-group $RG \ --forwarding-ruleset-name fwdrs-hub \ --location $LOCATION \ --outbound-endpoints id="$OUTBOUND_EP_ID" # 転送ルールを追加する(ドメイン名は末尾に「.」が必須) # intra.example.co.jp の問い合わせをオンプレDNS(192.168.1.10)へ転送する例 az dns-resolver forwarding-rule create \ --resource-group $RG \ --forwarding-ruleset-name fwdrs-hub \ --forwarding-rule-name rule-onprem \ --domain-name "intra.example.co.jp." \ --target-dns-servers ip-address=192.168.1.10 port=53 # ForwardingルールセットをVNetにリンクする az dns-resolver vnet-link create \ --resource-group $RG \ --forwarding-ruleset-name fwdrs-hub \ --vnet-link-name link-vnet-hub \ --id "$VNET_ID"

リンク後、Azure VM上の /etc/resolv.conf は変更不要です。168.63.129.16(Azure Provided DNS)がForwardingルールセットの転送ルールを参照し、オンプレDNS(192.168.1.10)へ転送してくれます。

【重要】--domain-name はFQDN形式(末尾に「.」が必要)で指定します。末尾なしで登録するとルールが機能しません。"intra.example.co.jp" ではなく "intra.example.co.jp." が正しい形式です。

Private EndpointのDNS統合でもPrivate DNSゾーンが必要になる

ここまで「corp.internal」のようなカスタムドメインを使ったVM間の名前解決を解説しました。AzureのPrivate DNSゾーンにはもう1つ重要な用途があります。BlobストレージやSQL DatabaseなどのPaaSサービスをPrivate Endpointでプライベート化する際のDNS統合です。

まず、VNetサービスエンドポイントとPrivate Endpointの違いを整理しておきます。

項目 VNetサービスエンドポイント Private Endpoint
プライベートIPの割り当て なし(サービスはパブリックIPのまま) あり(VNet内にプライベートIPを作成)
DNS解決 パブリックIPを返す(変わらない) プライベートIPを返す(Private DNS Zone連携)
パブリックアクセス完全遮断 不可(ファイアウォールで制限するのみ) 可能(public-network-access=Disabled)
別VNet・オンプレからの接続 不可(設定したVNetのサブネットのみ) 可(VNetピアリング・VPNで接続したVNetからも到達可能)
コスト 無料 有料(Private Endpointのリソース時間+通信量)

「サービスエンドポイントは設定済みだが、セキュリティ要件が厳しくなりパブリックアクセスを完全に閉じたい」という場面がPrivate Endpointへの移行タイミングです。

Private Endpointを作成すると、そのPaaSサービスのエンドポイントURLが引き続きパブリックIPを返してしまいます。これを解消してプライベートIPを返すようにするには、Azureが定めた命名規則に従った privatelink.* ゾーンを作成してVNetにリンクし、さらにDNSゾーングループを作成する必要があります。

Blobストレージを例にすると、手順は以下のとおりです。

1. BlobストレージのPrivate DNSゾーンを作成してVNetにリンクする

# Blob用のPrivate DNSゾーンを作成する az network private-dns zone create \ --resource-group $RG \ --name "privatelink.blob.core.windows.net" # VNetにDNSゾーンをリンクする(オートレジストレーションは不要) az network private-dns link vnet create \ --resource-group $RG \ --zone-name "privatelink.blob.core.windows.net" \ --name "dnslink-blob" \ --virtual-network $VNET \ --registration-enabled false

2. Private Endpointを作成してプライベートIPを確認する

Private Endpointの作成には az network private-endpoint create を使います。--group-id パラメータでサービスの種類を指定する点が重要で、Blob Storageの場合は blob を指定します。

# ストレージアカウントのリソースIDを取得する STORAGE_ID=$(az storage account show \ --name <ストレージアカウント名> \ --resource-group $RG \ --query id \ --output tsv) # Private Endpointを作成する(--group-id でサービス種別を指定) az network private-endpoint create \ --name pe-blob-storage \ --resource-group $RG \ --vnet-name $VNET \ --subnet $PE_SUBNET \ --private-connection-resource-id $STORAGE_ID \ --group-id blob \ --connection-name pe-blob-connection \ --location $LOCATION # 実行結果(抜粋) # { # "name": "pe-blob-storage", # "provisioningState": "Succeeded", # "type": "Microsoft.Network/privateEndpoints" # }

provisioningState: Succeeded が返れば作成完了です。割り当てられたプライベートIPを確認します。

# 割り当てられたプライベートIPを確認する(方法1: customDnsConfigs) az network private-endpoint show \ --name pe-blob-storage \ --resource-group $RG \ --query "customDnsConfigs[].{fqdn:fqdn,ip:ipAddresses[0]}" \ --output table # 出力例 # Fqdn Ip # ------------------------------------------------ ---------- # <ストレージ名>.blob.core.windows.net 10.0.2.4 # 方法2: NIC IDからIPアドレスを直接取得する(より確実) NIC_ID=$(az network private-endpoint show \ --name pe-blob-storage \ --resource-group $RG \ --query "networkInterfaces[0].id" \ --output tsv) az network nic show --ids $NIC_ID \ --query "ipConfigurations[0].privateIPAddress" \ --output tsv # 10.0.2.4

--group-id はサービスごとに異なります。PaaSサービスの種類と --group-id、対応するPrivate DNSゾーン名の一覧は後述の表を参照してください。

3. DNSゾーングループでPrivate EndpointとDNSゾーンを紐付ける

Private Endpointを作成した後、DNSゾーングループを作成するとプライベートIPがAレコードとして自動登録されます。この手順がPrivate Endpoint設定の中で最も見落とされやすい箇所です。VNetにDNSゾーンをリンクしただけでは不十分で、ゾーングループの作成が別途必要です。

# DNSゾーングループを作成してAレコードを自動登録する az network private-endpoint dns-zone-group create \ --resource-group $RG \ --endpoint-name pe-blob-storage \ --name zonegroup-blob \ --private-dns-zone "privatelink.blob.core.windows.net" \ --zone-name blob # nslookupでプライベートIPが返るか確認する(VNet内のLinux VMから実行) nslookup <ストレージ名>.blob.core.windows.net # Server: 168.63.129.16 # Address: 168.63.129.16#53 # # Non-authoritative answer: # <ストレージ名>.blob.core.windows.net # canonical name = <ストレージ名>.privatelink.blob.core.windows.net # Name: <ストレージ名>.privatelink.blob.core.windows.net # Address: 10.0.2.4

カスタムドメインゾーン(corp.internal)との違いは --registration-enabled false で固定する点です。privatelink.* ゾーンはDNSゾーングループが自動でAレコードを管理するため、オートレジストレーションは不要です。

4. curlとncでプライベート通信の経路を確認する

nslookupでプライベートIPが返るようになったら、curlコマンドで実際のHTTPS通信経路も確認します。HTTPステータスコードで閉域通信が確立できているかどうかを判断できます。

# curlでHTTPS通信の経路を確認する(VNet内のLinux VMから実行) # %{remote_ip} で実際の接続先IPアドレスを表示する curl -s -o /dev/null -w "%{http_code} %{remote_ip}\n" \ https://<ストレージ名>.blob.core.windows.net # 403 10.0.2.4 # → 接続先がプライベートIPになっていることを確認。403は認証なしアクセスを拒否しているだけ # ncコマンドで443ポートへの到達確認(Rocky Linux 9の場合はncatパッケージ) nc -zv <ストレージ名>.blob.core.windows.net 443 # Ncat: Connected to 10.0.2.4:443. # 接続先がプライベートIP(10.0.2.4)であればPrivate Endpoint経由と確認できる

curl で 403 Forbidden が返る場合、認証なしアクセスをAzureが正しく拒否しているだけです。ネットワーク経路としては正常で、Private Endpointを経由した閉域通信が確立されています。000(タイムアウト)が返る場合はDNS設定またはNSGの確認が必要です。ポート確認コマンドの詳細は「Linux ポート確認の全コマンド」を参照してください。

PaaSサービスの種類によって --group-id と privatelink.* ゾーン名が変わります。主なものをまとめます。

PaaSサービス --group-id Private DNSゾーン名
Blob Storage blob privatelink.blob.core.windows.net
Azure Files file privatelink.file.core.windows.net
Queue Storage queue privatelink.queue.core.windows.net
Azure SQL Database sqlServer privatelink.database.windows.net
Azure Key Vault vault privatelink.vaultcore.azure.net
Azure Container Registry registry privatelink.azurecr.io
Azure App Service sites privatelink.azurewebsites.net

複数サービスへPrivate Endpointを設定する場合、サービスごとにPrivate DNS Zoneを作成してVNetにリンクする必要があります。同一VNetに複数のDNS Zoneをリンクすることは可能で、ゾーン名が異なれば競合しません。ハブアンドスポーク構成の場合、DNS ZoneのリンクはハブVNetに集約するのが管理しやすいです。

5. StorageアカウントのパブリックアクセスをDisabledにする

DNSゾーングループの設定が完了したら、StorageアカウントのパブリックアクセスをDisabledにします。これでインターネット側からのアクセスが完全に遮断され、VNet内のPrivate Endpoint経由でのみ接続できる「クローズドStorage」が完成します。

# StorageアカウントのパブリックアクセスをDisabledにする az storage account update \ --name <ストレージアカウント名> \ --resource-group $RG \ --public-network-access Disabled # 設定が反映されたことを確認する az storage account show \ --name <ストレージアカウント名> \ --resource-group $RG \ --query publicNetworkAccess # 出力例 # "Disabled"

設定後に実際の通信制御を確認します。VNet外(自分のPC等)からアクセスを試みると拒否され、VNet内のLinux VMからはプライベートIP経由で正常にアクセスできることを確認してください。

# VNet外のPC(インターネット経由のaz CLI)から実行 → 拒否される az storage blob list \ --account-name <ストレージアカウント名> \ --container-name mycontainer \ --auth-mode login 2>&1 # This request is not authorized to perform this operation. # VNet内のLinux VMから実行 → 成功(プライベートIP経由のため) az storage blob list \ --account-name <ストレージアカウント名> \ --container-name mycontainer \ --auth-mode login # [] ← 空のリストが返れば正常(コンテナが空の場合)

VNetピアリングやVPN Gatewayで接続したオンプレミス環境からは同じプライベートIPで引き続き到達できます。

名前解決できない時のトラブルシュート

1. VNetリンクの状態を確認する

最も多い原因がVNetリンクの未設定または不完全な状態です。

# VNetリンクの一覧と状態を確認 az network private-dns link vnet list \ --resource-group $RG \ --zone-name "corp.internal" \ --output table # 期待する出力 # Name ProvisioningState VirtualNetworkLinkState # link-vnet-main Succeeded Completed

2. VMのDNSリゾルバ設定を確認する

AzureのPrivate DNSゾーンを参照するには、VMのDNSリゾルバがAzureデフォルトDNS(168.63.129.16)を向いている必要があります。カスタムDNSサーバーに変更している場合は要注意です。

# Rocky Linux 9でのDNSリゾルバ確認 cat /etc/resolv.conf # Azureデフォルトリゾルバが含まれているか確認 # nameserver 168.63.129.16 # nmcliで現在のDNS設定を確認 nmcli dev show | grep DNS

/etc/resolv.confの詳しい設定方法は「Linux DNS 設定の基本」を参照してください。VNetのDNSサーバー設定を変更した場合、168.63.129.16を条件転送先として追加するか、カスタムDNSサーバーからAzureデフォルトDNSへの条件付きフォワーダーを設定する必要があります。

3. DNSキャッシュをクリアする(systemd-resolved環境)

nslookupは正しいプライベートIPを返しているのに、curlの接続先が古いパブリックIPのままになる場合があります。Linux VMのDNSキャッシュが残っていることが原因です。systemd-resolved を使っている環境(Ubuntu 24.04 LTS等)ではキャッシュをクリアします。

# systemd-resolvedのDNSキャッシュをクリアする sudo resolvectl flush-caches # キャッシュクリア後に再確認 nslookup <ストレージ名>.blob.core.windows.net # curlの接続先IPも再確認する curl -s -o /dev/null -w "http_code: %{http_code} remote_ip: %{remote_ip}\n" \ https://<ストレージ名>.blob.core.windows.net # http_code: 403 remote_ip: 10.0.2.4 ← プライベートIPになっていれば正常

Rocky Linux 9(NetworkManager管理下)では sudo systemctl restart NetworkManager でも同様の効果が得られます。ただし、000(タイムアウト)が返る場合はDNSキャッシュが原因ではないため、次の手順でNSGとPrivate Endpointの設定を確認してください。

4. NSGのDNSポートを確認する

NSG(ネットワークセキュリティグループ)のルールでUDP 53番ポートがブロックされているケースがあります。DNS Private Resolverを使っている場合はInbound Endpoint専用サブネット向けのNSGにDNSポートの許可ルールが必要です。

# NSGのルール一覧を確認 az network nsg list --resource-group $RG --output table # 特定NSGのルールを詳細確認(NSG名はAzureポータルまたは上記コマンドで取得) az network nsg rule list \ --resource-group $RG \ --nsg-name \ --output table # DNS Private Resolver使用時:Inbound Endpointサブネット向けNSGにDNSポートを許可する az network nsg rule create \ --resource-group $RG \ --nsg-name nsg-dns-inbound \ --name allow-dns-from-onprem \ --priority 100 \ --direction Inbound \ --protocol Udp \ --destination-port-ranges 53 \ --access Allow

DNSはUDP/TCP 53番ポートを使います。ポートの開放状況はLinux VM上からも確認できます。ssコマンドやlsofコマンドを使ったポート確認の方法は「Linux ポート確認の全コマンド」を参照してください。

5. DNSゾーングループの有無を確認する(Private Endpoint利用時)

Private Endpointのプライベートipがnslookupで返ってこない場合、DNSゾーングループが作成されていないケースが多いです。VNetにDNSゾーンをリンクしただけでは不十分で、ゾーングループの作成が別途必要です。

# DNSゾーングループの存在を確認する az network private-endpoint dns-zone-group list \ --resource-group $RG \ --endpoint-name pe-blob-storage \ --output table # ゾーングループが存在しない場合はnslookupがパブリックIPを返し続ける

6. curlで000が返る場合の対処(Private Endpoint利用時)

nslookupでプライベートIPが返るにもかかわらず curl で000(接続タイムアウト)が返る場合、ネットワーク到達性の問題です。NSGでポート443のアウトバウンドがブロックされているか、VMとPrivate Endpointが異なるサブネットのNSGで分断されていないか確認します。

# Private Endpointのプロビジョニング状態を確認する az network private-endpoint show \ --name pe-blob-storage \ --resource-group $RG \ --query "provisioningState" \ --output tsv # "Succeeded" が返れば作成は完了している # VM用サブネットに適用されているNSGのルールを確認する az network nsg rule list \ --resource-group $RG \ --nsg-name \ --output table # ポート443のアウトバウンド許可ルールが存在するか確認する

VMを再起動するとDNSキャッシュがリセットされ、名前解決の問題が解消するケースもあります。ただし、000(タイムアウト)の場合はDNSキャッシュではなくNSGやPrivate Endpointの設定が原因であることが多いため、まず上記の確認を先に行ってください。

7. Private Endpoint専用サブネットへの作成が失敗する(PrivateEndpointNetworkPoliciesEnable)

az network private-endpoint create 実行時に「PrivateEndpointNetworkPoliciesEnable」というエラーが出た場合、対象サブネットのNetwork Policiesが有効になっています。サブネット作成時に --disable-private-endpoint-network-policies true を付け忘れたケースです。

# 既存サブネットのNetwork Policiesを無効化する(後から修正する場合) az network vnet subnet update \ --resource-group $RG \ --vnet-name $VNET \ --name $PE_SUBNET \ --disable-private-endpoint-network-policies true # 変更後に再度Private Endpoint作成を試みる

新規サブネット作成時は az network vnet subnet create に --disable-private-endpoint-network-policies true を最初から含めるのが確実です。

8. DNS Private ResolverのForwardingルールセットがVNetにリンクされていない

Azure VMからオンプレのドメインが解決できない場合、ForwardingルールセットをVNetにリンクするのを忘れているケースがあります。

# ForwardingルールセットのVNetリンク状況を確認する az dns-resolver vnet-link list \ --resource-group $RG \ --forwarding-ruleset-name fwdrs-hub \ --query "[].{Name:name, VNet:virtualNetwork.id}" -o table # 出力例(リンク済みの場合) # Name VNet # link-vnet-hub /subscriptions/.../virtualNetworks/vnet-main # 出力が空の場合はリンクが未設定 → az dns-resolver vnet-link create で追加する

9. Public Network無効化後にCIパイプラインからアクセスできなくなった

Public Network Accessを無効化すると、Azure VNet外からのアクセスはすべて遮断されます。GitHub ActionsなどのCIパイプラインからBlob操作が必要な場合は、以下のどちらかを検討してください。

・Private Endpointを作成したVNetとCIランナーのVNetをVNet Peeringで接続する
・セルフホストランナーをVNet内のLinux VMに配置し、VNet内からBlob操作を実行する

なお、一時的な検証目的であれば --public-network-access Enabled で元に戻し、Private Endpointの動作確認後に再度Disabledにする手順を踏むと安全に切り替えられます。

まとめ:azure private dns の運用ポイント

Azure Private DNSゾーンの設定手順をまとめます。

やりたいこと azコマンド(操作内容)
Private DNSゾーンを作成する az network private-dns zone create --resource-group RG --name "corp.internal"
VNetにリンクする az network private-dns link vnet create --zone-name "corp.internal" --virtual-network vnet-main --registration-enabled false
AレコードをCLIで追加する az network private-dns record-set a add-record --zone-name "corp.internal" --record-set-name "vmapp01" --ipv4-address "10.0.1.4"
オートレジストレーションを有効化する az network private-dns link vnet update --zone-name "corp.internal" --registration-enabled true
登録済みレコードを確認する az network private-dns record-set list --zone-name "corp.internal" --output table
VNetリンクの状態を確認する az network private-dns link vnet list --zone-name "corp.internal" --output table
DNS Private Resolverを作成する az dns-resolver create --dns-resolver-name dns-resolver-hub --id <vnet-id>
Inbound Endpointを作成する(オンプレ→Azure) az dns-resolver inbound-endpoint create --inbound-endpoint-name inbound-ep --ip-configurations private-ip-allocation-method=Dynamic id=<subnet-id>
Outbound Endpoint+Forwardingルールセットを作成する az dns-resolver forwarding-ruleset create --outbound-endpoints id=<ep-id>
転送ルールを追加する(Azure→オンプレ) az dns-resolver forwarding-rule create --domain-name "ドメイン." --target-dns-servers ip-address=x.x.x.x port=53
ForwardingルールセットをVNetにリンクする az dns-resolver vnet-link create --forwarding-ruleset-name fwdrs-hub --id <vnet-id>
PE専用サブネットのNetwork Policiesを無効化する az network vnet subnet create --disable-private-endpoint-network-policies true
Blob用Private DNSゾーンを作成する az network private-dns zone create --name "privatelink.blob.core.windows.net"
BlobへのPrivate Endpointを作成する az network private-endpoint create --group-id blob --connection-name pe-blob-connection ...
割り当てられたプライベートIPを確認する az network private-endpoint show --query "customDnsConfigs[].ipAddresses[]" --output tsv
DNSゾーングループを作成してAレコードを自動登録する az network private-endpoint dns-zone-group create --endpoint-name pe-name --name zonegroup --private-dns-zone "privatelink.blob.core.windows.net" --zone-name blob
StorageのパブリックアクセスをDisabledにする az storage account update --public-network-access Disabled
DNSキャッシュをクリアする sudo resolvectl flush-caches

Azure Private DNSゾーンを使えば、VNet内のVMをIPアドレスではなくホスト名で管理できます。特にオートレジストレーションを活用すると、VMのスケールアウト時の名前登録が自動化され、手動ミスによる障害を防ぎやすくなります。VPN GatewayやExpressRouteでオンプレミスと接続する構成では、DNS Private Resolverを組み合わせることでオンプレ↔Azure間の双方向DNS統合をVM保守なしで実現できます。BlobストレージやKey VaultなどをPrivate Endpointで閉域化する際も、privatelink.* ゾーンとDNSゾーングループを組み合わせることでシームレスなDNS統合が実現します。Private Endpoint専用サブネットの --disable-private-endpoint-network-policies true を忘れずに設定し、nslookupでプライベートIPが返り、curlで403が返ることを確認してから本番環境に適用するようにしてください。

Linuxサーバーを使ったクラウド実務スキルをさらに深めたい方は、下のリンクからAzure対応のセミナー内容をご確認ください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Azure対応セミナーの詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。