⚠️

Private Endpoint宛のトラフィックをUDRで制御する際の動作と注意点

に公開

はじめに

Private Endpoint宛のトラフィックをUDRで制御する(経路上に Azure Firewall を挟んで検査する等)場合、ネットワーク経路設計における注意点があります。

  • Private Endpointを設置しているサブネットでPrivateEndpointNetworkPolicies(UDR)の有効化が必要
  • 原則SNATが必要

Private Endpoint宛の通信をUDRで制御する構成を検討する機会があり、個人のAzure環境でPoCしながら動作を理解してみました。
VNetのルーティング情報を読み解きながら、Private Endpoint宛のトラフィックにUDRを適用する時の注意点や振る舞いを解説します。

Private Endpointを使用しない時のルート

まずはPaaS(ストレージアカウントとSQL Database)を作成し、Private Endpointを作らずに VMから接続します。

この段階ではパブリックIPアドレスで名前解決されます。

$ curl -v telnet://stazpocusw2.blob.core.windows.net:443
* Host stazpocusw2.blob.core.windows.net:443 was resolved.
* IPv6: (none)
* IPv4: 57.150.149.97
*   Trying 57.150.149.97:443...
* Connected to stazpocusw2.blob.core.windows.net (57.150.149.97) port 443

VMのルーティングテーブルを確認すると、VNet外はNext HopがInternetとなっています。これはVNetのデフォルト状態です。

$ az network nic show-effective-route-table --resource-group azpoc-vm --name vm-azpoc-usw2-01358_z1 -o table
Source    State    Address Prefix    Next Hop Type    Next Hop IP
--------  -------  ----------------  ---------------  -------------
Default   Active   192.168.0.0/24    VnetLocal
Default   Active   0.0.0.0/0         Internet
... (Next Hop TypeがNoneは省略)

Private Endpoint設置時のシステムルート

次に、Private Endpoint用のサブネットを追加し、ストレージアカウントとSQL DatabaseのPrivate Endpointを設置します。
Private DNS Zoneも併せて作成しVNetにリンクしておきます。
これはよくあるPaaS接続パターンではないでしょうか。

この状態でVMのルートテーブルを確認してみると、Private Endpoint宛の/32システムルート(Next Hop TypeがInterfaceEndpointの2行)が自動追加されています。
ルーティングテーブルはロンゲストマッチで経路選択されるので、Private Endpoint宛の通信は常にこの経路が選ばれます。

$ az network nic show-effective-route-table --resource-group azpoc-vm --name vm-azpoc-usw2-01358_z1 -o table
Source    State    Address Prefix    Next Hop Type      Next Hop IP
--------  -------  ----------------  -----------------  -------------
Default   Active   192.168.0.0/24    VnetLocal
Default   Active   0.0.0.0/0         Internet
Default   Active   192.168.0.68/32   InterfaceEndpoint
Default   Active   192.168.0.69/32   InterfaceEndpoint
... (Next Hop TypeがNoneは省略)

VMからtelnetでストレージアカウントとSQL DatabaseへTCP接続をしてみると、Private DNS ZoneのAレコード値で名前解決され、TCP接続に成功します。

$ curl -v telnet://stazpocusw2.blob.core.windows.net:443
* Host stazpocusw2.blob.core.windows.net:443 was resolved.
* IPv6: (none)
* IPv4: 192.168.0.68
*   Trying 192.168.0.68:443...
* Connected to stazpocusw2.blob.core.windows.net (192.168.0.68) port 443

$ curl -v telnet://sql-azpoc-usw2-01.database.windows.net:1433
* Host sql-azpoc-usw2-01.database.windows.net:1433 was resolved.
* IPv6: (none)
* IPv4: 192.168.0.69
*   Trying 192.168.0.69:1433...
* Connected to sql-azpoc-usw2-01.database.windows.net (192.168.0.69) port 1433

VNet Peering先のPrivate Endpointへのルート

次は、Private EndpointをVNet2のみに設置し、VNet1とはPeeringした構成で確認します。

VNet1のVMのルートテーブルを確認してみると、先ほどと同じように/32のシステムルートが伝播されていることが確認できます。
Private Endpointのシステムルートは設置しているVNetだけではなく、PeeringしているVNetにも伝播されます。

$ az network nic show-effective-route-table --resource-group azpoc-vm --name vm-azpoc-usw2-01358_z1 -o table
Source    State    Address Prefix    Next Hop Type      Next Hop IP
--------  -------  ----------------  -----------------  -------------
Default   Active   192.168.0.0/24    VnetLocal
Default   Active   192.168.1.0/26    VNetPeering
Default   Active   0.0.0.0/0         Internet
Default   Active   192.168.1.4/32    InterfaceEndpoint
Default   Active   192.168.1.5/32    InterfaceEndpoint
... (Next Hop TypeがNoneは省略)

つまり、Peeringを介さず直接PaaSへ接続していることになります。
結果的に構成図の経路と同等の振る舞いとなるように、Azure SDNが裏でいい感じに制御してくれているようです。

VMからtelnetでストレージアカウントとSQL DatabaseへのTCP接続も成功します。
Private Endpoint宛のトラフィックをUDRで制御する要件がなければ、このままの構成で問題ありません。

# vm serial console
$ curl -v telnet://stazpocusw2.blob.core.windows.net:443
* Host stazpocusw2.blob.core.windows.net:443 was resolved.
* IPv6: (none)
* IPv4: 192.168.1.4
*   Trying 192.168.1.4:443...
* Connected to stazpocusw2.blob.core.windows.net (192.168.1.4) port 443

$ curl -v telnet://sql-azpoc-usw2-01.database.windows.net:1433
* Host sql-azpoc-usw2-01.database.windows.net:1433 was resolved.
* IPv6: (none)
* IPv4: 192.168.1.5
*   Trying 192.168.1.5:1433...
* Connected to sql-azpoc-usw2-01.database.windows.net (192.168.1.5) port 1433

Private Endpoint宛の通信をUDRで制御する時のルート

次に、Private Endpoint宛のトラフィックをUDRでAzure Firewall経由にし、トラフィックを検査してみます。
ここでは設計上の注意として PrivateEndpointNetworkPoliciesの有効化SNAT(経路対称化) の考慮が必要です。

Private Endpoint宛のトラフィックのNext HopをAzure FirewallとするUDRを作成し、VMのサブネットに割り当てます。
Private Endpointサブネットのアドレス(192.168.1.0/26)をNext Hop = Virtual Appliance(FirewallのプライベートIP:192.168.0.68)にします。

この状態でVMのルートテーブルをState列に注目して確認してみます。
UDRのルート(Source列がUserの行)が挿入されており、Address Prefixが同じ/26のシステムルート(Next Hop TypeがVNet Peeringの行)はInvalidとなりました。システムルートはUDRで上書きができるためです。
しかし、まだ/32のシステムルート(Next Hop TypeがInterfaceEndpointの2行)がActiveになっています。

$ az network nic show-effective-route-table --resource-group azpoc-vm --name vm-azpoc-usw2-01358_z1 -o table
Source    State    Address Prefix    Next Hop Type      Next Hop IP
--------  -------  ----------------  -----------------  -------------
Default   Active   192.168.0.0/24    VnetLocal
Default   Invalid  192.168.1.0/26    VNetPeering
Default   Active   0.0.0.0/0         Internet
User      Active   192.168.1.0/26    VirtualAppliance   192.168.0.68
Default   Active   192.168.1.4/32    InterfaceEndpoint
Default   Active   192.168.1.5/32    InterfaceEndpoint

このままではロンゲストマッチでAddress Prefixが/32のルートが選択されてしまい、Private Endpoint宛のトラフィックはInterfaceEndpoint宛となり、Azure Firewallに転送されません。

Private Endpoint宛のトラフィックにUDRを適用するには、Private Endpointを設置しているVNet2側のサブネットの設定で、PrivateEndpointNetworkPoliciesのルートテーブルを有効化する必要があります。

PrivateEndpointNetworkPoliciesを有効化した後、再度VMのルートテーブルを確認してみると、Address Prefixが/32のシステムルートのStateがInvalidに変わりました。これでUDRのルート(Source列がUserの行)が選択されるようになります。

$ az network nic show-effective-route-table --resource-group azpoc-vm --name vm-azpoc-usw2-01358_z1 -o table
Source    State    Address Prefix    Next Hop Type      Next Hop IP
--------  -------  ----------------  -----------------  -------------
Default   Active   192.168.0.0/24    VnetLocal
Default   Invalid  192.168.1.0/26    VNetPeering
Default   Active   0.0.0.0/0         Internet
User      Active   192.168.1.0/26    VirtualAppliance   192.168.0.68
Default   Invalid  192.168.1.4/32    InterfaceEndpoint
Default   Invalid  192.168.1.5/32    InterfaceEndpoint

Azure Firewallにアプリケーションルールを投入しておきます。VNet1からすべての宛先を許可しています。

これでVMからAzure Firewall宛のUDR設定と、Azure Firewallのルール設定ができたので、VMから疎通をしてみます。

Azure Firewallでアプリケーションルールを使用している構成で疎通確認を行うときには、使用するプロトコルで注意が必要です。
アプリケーションルールでDenyアクションが動いた場合でも、L4のTCP 3way handshakeは成功します。
https://jpaztech.github.io/blog/network/firewall-rules/

TCP接続だけではアプリケーションルールの疎通確認にはならないので、L7のプロトコルを使う必要があります。
今回はストレージアカウントはAzure CLI、SQL Databaseはsqlcmdで疎通確認を行います。

Azure CLIを用いたBLOBストレージへの接続も成功します。

$  az storage blob list --auth-mode login --account-name stazpocusw2 -c poc -o table
Name      Blob Type    Blob Tier    Length    Content Type    Last Modified              Snapshot
--------  -----------  -----------  --------  --------------  -------------------------  ----------
test.txt  BlockBlob    Hot          5         text/plain      2025-09-21T05:07:32+00:00

sqlcmdで接続も成功しました。

$ sqlcmd -S sql-azpoc-usw2-01.database.windows.net -U azpoc -d sqldb-azpoc-usw2-01
Password: 
1> SELECT client_net_address FROM sys.dm_exec_connections WHERE session_id = @@SPID;
2> GO
client_net_address                              
------------------------------------------------
192.168.0.69  

L7のプロトコルを用いた疎通確認も成功し、Azure FirewallのログにもAllowアクションとして記録されました。

まとめ

Private EndpointをVNetに設置すると、Private EndpointのプライベートIPアドレス/32のInterfaceEndpointシステムルートが自動伝播(Peering先のVNetにも)されます。Private Endpoint宛のトラフィックはロンゲストマッチで常に/32の経路が選択され、ダイレクトに到達します。

UDRでPrivate Endpoint宛のトラフィックを制御する場合は、Private Endpointを置いている側のサブネットでPrivateEndpointNetworkPoliciesを有効化(これにより/32のInterfaceEndpointシステムルートがInvalidになりUDRが効く)します。
また、UDRでPrivate Endpointの戻りのトラフィックを制御することはできないので、Azure Firewallでトラフィック検査をする場合は、経路の対称化のためにSNATが必要です。

参考

https://learn.microsoft.com/ja-jp/azure/private-link/inspect-traffic-with-azure-firewall

https://qiita.com/Isato-Hiyama/items/6b90904887fcfe12b2a9

https://blog.cloudtrooper.net/2025/01/20/private-link-reality-bites-private-endpoints-are-an-illusion/

https://journeyofthegeek.com/2020/09/10/interesting-behaviors-with-private-endpoints-new/

https://blog.cloudtrooper.net/2020/05/23/filtering-traffic-to-private-endpoints-with-azure-firewall/

Discussion