背景
実機検証した際、AppGW→→AzFW→→APIMの構成を作って、AzFW上でNetwork ruleを作ってAppGWからWebappへの通信を許可しましたが、AppGWの正常性Probeは失敗して、unhealthの状態に陥ります。そしてNetwork ruleを削除して、Application ruleを作成して通信許可しました。今度は無事に正常性Probeが成功になり、backend はHealth状態と示してくれました。
なぜこんな状況になるでしょうか。
よく発生しうるシナリオなので、ここで説明を加えてメモします。
調査結果
1.Network ruleで許可した場合、APIM側のログはprobe healthの通信が記録はないです。
つまりprobe healthは到達していません。
AppGwのbackend正常性もunreachable となっています。
AzFWのログにはちゃんと通信を許可した記録があります。
2.Application ruleで許可したら、APIM側のログにはprobe health の通信が記録されました。
3.気づき、Application ruleで許可したら、APIM側のログに送信元はAzFWのinstanceIPになっています。
なるほど、SNATが働いていますね。すぐここで原因が判明できました。
4.原因:
Network ruleで許可した場合、AzFWによるSNATはしません。つまり、APIM側でみた送信元IPはAPPGWのIPになります。APIMがTCP 3 way handshakeで直接AppGWに対してAckします。このAckはAzFWを経由しないです。
簡単にいうと、Network ruleはSNATをしないため、以下のように非対称ルートになります。
TCP行く通信:AppGW→→AzFW→→APIM
TCP戻り通信:APIM→→AppGW
これでProbe health はhttpなので、TCPが確立できなければ、もちろんhttpも到達できません。
これが理由で、AzFWに通信許可のログはありますが、APIM側ではprobe healthの記録はありません。
Application ruleに変えた場合、AzFWによるSNATはしますので、APIM側でみた送信元IPはAzFWのIPになります。APIMのAckはAzFWを経由します。
簡単にいうと、Applicaiton ruleはSNATをするため、以下のように対称ルートになります。
問題なく、TCP通信が確立できます。
TCP行く通信:AppGW→→AzFW→→APIM
TCP戻り通信:APIM→→AzFW→→AppGW
大事な補足
もう一歩踏み込んでnetwork rule のSNATについて調査をしました。
Network ruleの場合、SNATする際もあります。これはInternet向けの通信のみに対してです。東西通信(社内通信とか)の場合、宛先がプライベート IP 範囲(RFC 1918: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 など)の場合、SNAT は適用されず、元の送信元 IP が保持されます。
Azure VM から Internetへのアウトバウンド通信を Azure Firewall の Network Rule で許可した場合、SNAT はデフォルトで適用されます。送信元 IP アドレスが VM のIP から AzFW の公開 IP に変換されます。
Network Rule は L4 (TCP/UDP) レベルで動作し、宛先が公開 IP (例: 0.0.0.0/0 や Internet 範囲)の場合、自動的に SNAT が適用されます。 これにより、VM のプライベート IP が外部に露出せず、AzFW の公開 IP が使用されます。
例外: 宛先がプライベート IP 範囲(RFC 1918: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 など)の場合、SNAT は適用されず、元の送信元 IP が保持されます。
カスタマイズ: SNAT 動作を変更したい場合、AzFW の設定でプライベート範囲を調整可能です(例: 常に SNAT するよう 255.255.255.255/32 に設定)。デフォルトでは Internet 向けに SNAT が有効です。
感想
なるほど、AzFWを利用する構成には、SNATの働きをもちゃんと留意しなければいけませんね。