Azure との VPN 接続がうまくいかない場合のデバッグ方法


いつの間にか Azure VPN Gateway の診断ログが取れるようになってました。
これがあればユーザー側でのデバッグが大分やりやすくなるので、周知の意味も込めてメモ程度に残しておきます。

診断ログの設定方法

まず、診断ログは [診断設定] のブレードから、個別に有効化します。

適当な名前とストレージ等の出力先を指定し、有効化したいログの種類にチェックします。VPN 接続時のネゴシエーション周りは IKEDiagnosticLogs だけで十分なはず。(他のログについても順次確認中)

しばらく待つと指定したストレージに insights-logs-ikediagnosticlog という名前でコンテナが作成され、その中を掘っていくと毎時 PT1H.json というファイルが吐き出されていることが確認できます。

ログ解析のポイント

PT1H.json を開いてみると、ログは JSON Lines (各行が JSON 形式) のフォーマットで出力されていることがわかります。適当に JSON が見やすいエディタを使いましょう。

ここからは Azure 固有の話ではなく IPsec VPN のネゴシエーション周りの一般的なお話ですが、接続を確立しようとする際は、SA INIT の通信が行われます。
(SA: Security Association, INIT : Initialize のことです)

Azure とオンプレ側の VPN デバイスのどちらから接続を始めても問題ありませんが、先に接続要求を送ったほうを Initiator、接続要求を受け取ったほうを Responder と呼びます。で、SA INIT のフェーズでは Initiator 側が initiator cookie (iCookie) だけセットした状態で、responder cookie (rCookie) が空 (0x0) のパケットを送付してネゴシエーションを始めます。(受け取った Responder 側が rCookie をセットして返します)

なので、ログの中で “iCookie : 0x0” とか “rCookie : 0x0” の行を探しましょう。(闇雲にログを見るのではなく、SA INIT を始めた行から見ていくことをオススメします。)

以下の例では、Azure 側としては [RECV Network Packet] ということで、パケットを受け取ったと書かれているので、オンプレミス側 (FortiGate) が Initiator で、Azure VPN Gateway は Responder 担っていることがわかります。(図では、549-552 行目が受け取った SA INIT のデバッグ ログで、それに対しての応答が 553-555 行目になっています。)

あ、毎度のことながら IP アドレスは FortiGate 側を ff.ff.ff.ff、Azure 側を aa.aa.aa.aa でマスクしてますのでご容赦を。

この例では、iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd となっていますが、同じタイミングの VPN デバイスのログをみても同一の Cookie でログが見つかるはずです。(以下はあくまでも FortiGate のデバッグ ログの例なので、機種によって出力されるログは異なります。FortiGate の場合は 16 進数を意味する 0x なしでログが出るみたいなので、 1df26d566a7f45fa とかで検索しています。)

ということで、あとは何の処理で失敗しているのかをゴリゴリ見ていきましょう。(確認ポイントは状況によって違うのと、そもそも VPN の接続時のフローとかを把握していないとダメなので、 細かい話は Cisco のドキュメントとか見て頑張ってください。 )

正常時のログサンプル (抜粋)

{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x0 ; Exchange type : IKEv2 SA Init Mode ; Length : 396 ; NextPayload : SA ; Flags : 0x8(INITIATOR,REQUEST) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received SA INIT","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received Ike payload: Policy1:AES-CBC-256 SHA1 SHA1 DhGroup2 Policy2:3DES SHA1 SHA1 DhGroup2 Policy3:AES-CBC-256 SHA256 SHA256 DhGroup2 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Receiving MM Packet for tunnel Id 0x0 iCookie 0x1DF26D566A7F45FA and rCookie 0x29D6549E71D8FADD: Receiving MM Nonce","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending IKE SA_INIT response packet with tunnelId 0x0, iCookie 0x1DF26D566A7F45FA and rCookie 0x29D6549E71D8FADD","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending Ike payload for tunnel Id 0x0: Auth:PreShared Key- Responder Policy:AES-CBC-256 SHA1 DhGroup2 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4236930Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 SA Init Mode ; Length : 364 ; NextPayload : SA ; Flags : 0x20(RESPONDER,RESPONSE) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Auth Mode ; Length : 284 ; NextPayload : ENCR ; Flags : 0x8(INITIATOR,REQUEST) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received IKE AUTH message","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received Traffic Selector payload - Number of TSIs 1: StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0 Number of TSRs 1:StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Proposed Traffic Selector payload will be - Number of TSIs 1: StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0 Number of TSRs 1:StartAddress 0.0.0.0 EndAddress 255.255.255.255 PortStart 0 PortEnd 65535 Protocol 0","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Received IPSec payload: Policy1:AES-CBC-256 SHA1 Policy2:3DES SHA1 Policy3:AES-CBC-256 SHA256 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending SA AUTH response message for tunnelId 0x5 and tsId 0x13","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending IPSec policy Payload for tunnel Id 0x5, tsId 0x13: Policy1:AES-CBC-256 SHA1 ","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: IKE Tunnel created for tunnelId 0x5","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Auth Mode ; Length : 204 ; NextPayload : ENCR ; Flags : 0x20(RESPONDER,RESPONSE) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: IKE Tunnel closed for tunnelId 0x3 with status Deleted via RPC call","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:06.4440063Z", "level": "Informational", "properties": {"message":"Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Sending IPSEC SA delete for tunnelId 0x3 and tsId 0x12","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:08.4569360Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x0(RESPONDER,REQUEST) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:08.4575869Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x28(INITIATOR,RESPONSE) ; Messid : 0x00000000","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:10.4754992Z", "level": "Informational", "properties": {"message":"[SEND Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x0(RESPONDER,REQUEST) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}
{ "resourceid": "/SUBSCRIPTIONS/49DDE45F-5712-44B2-B0AB-296BDE83AF6B/RESOURCEGROUPS/CALEDFWLCH/PROVIDERS/MICROSOFT.NETWORK/VIRTUALNETWORKGATEWAYS/CALEDFWLCH-VPNGW-JW", "category": "IKEDiagnosticLog", "operationName": "IKELogEvent", "time": "2019-01-28T15:19:10.4754992Z", "level": "Informational", "properties": {"message":"[RECV Network Packet] Remote ff.ff.ff.ff:500: Local aa.aa.aa.aa:500: Packet : IKEVersion : IKEv2 ; iCookie : 0x1df26d566a7f45fa ; rCookie : 0x29d6549e71d8fadd ; Exchange type : IKEv2 Informational Mode ; Length : 76 ; NextPayload : ENCR ; Flags : 0x28(INITIATOR,RESPONSE) ; Messid : 0x00000001","instance":"GatewayTenantWorker_IN_0"}}

気が向いたら何パターンかありがちな設定ミス時のログの例でも追記します。

VPN 切断時のチェックポイント

VPN の切断・再接続時のログは、insights-logs-tunneldiagnosticlog コンテナー内に同じく PT1H.json ファイルとして出力されています。中を見ると、status が Disconnected (切断された) もしくは Connected (接続された) ということと、 stateChangeReason として理由が明記されているので、ざっくりとした切断理由が分かります。

以下の例だと DPD timed out で Disconnected になっているので、Azure VPN Gateway からの DPD (Dead Peer Detection) の通信にオンプレミス側の FortiGate が応答を返さなかったので切断されたことが分かります。(これは、当然 FortiGate 自身が無応答だった可能性もありますが、Internet の経路上で問題があった可能性もゼロではありません) オンプレミス側のデバッグログ等とも見比べて、どこで何が起きていたかを調査しましょう。

また、Connected に変わった際は RemotelyTriggered で発生したと書かれています。したがって、FortiGate 側が Initiator となって接続要求を送ってきたので、Azure VPN Gateway としてはそれを受け入れて接続が完了したという事になります。(メンテナンス等で Azure 側から切断、再接続をした際は LocalTriggered とかになるはずです)

ルーティング観点のチェックポイント

VPN で BGP を使っている場合など、トンネルは張れているのにルーティングの問題で通信出来ない場合もあります。そうした際は insights-logs-routediagnosticlog 内の PT1H.json ファイルでルーティング情報を確認しましょう。以下の例では、 VPN の切断・再接続に伴って発生した、経路の消失、BGP の Peer Down、BGP の Peer Up、経路の学習が確認できます。また、一部マスクをしていますが、学習した経路も確認できるので、オンプレミス側から BGP で正しく経路を出せていない場合なども一目で分かるはずです。

その他

Azure との VPN できない場合の VPN デバイス側のトラシューは以下なども併せてどうぞ。


[Day5] Azure のネットワークがさっぱり分からん



# Microsoft Azure Tech Advent Calendar 2018 の 5 日目です。

今回は、インフラ野郎が大好きな Azure のネットワークについて整理してみたいと思います。

 

4 種類の Azure ネットワーク

Azure  のネットワークは、大きく 4 種類に分かれます。

  • Private IP (Azure VNET) のネットワーク: VNET 内に展開される VM 等
  • Public IP (VNET 外) のネットワーク: VNET 外に配置される各種 PaaS や、VM の Public IP 等
  • Azure 基板側のネットワーク: バックボーン ネットワークや、物理サーバー用 (ユーザーからは見えない部分)
  • Azure 外に存在するネットワーク: Azure DNS や Traffic Manager、CDN、FrontDoor 等

ざっくり図にすると、こんな感じになります。

# よくある誤解

たまに Azure Storage や SQL Database 等の PaaS に対して VPN 接続したいという話を聞きますが、VPN 接続出来るのは VNET のみですので、Public IP の世界に接続したい場合には ExpressRoute の Microsoft Peering が必要です。(もしくは、App Service Environment や SQL Database Managed Instance のように VNET 内に専用のインスタンスを建てられる上位プランを使用する必要があります。)

また、Azure のサービスであっても、Azure データセンター外の Public IP からサービスを提供する Azure DNS, Traffic Manager, CDN, FrontDoor 等のサービスについては、VPN でも ExpressRoute 経由でもアクセスすることが出来ません。(これらは Internet 経由のアクセスを前提としたサービスなので、閉域環境で使う事を想定されていません) くわえて、内部的にこれらを使っているもの (例えば Azure Portal とか) に対しても、ExpressRoute 経由で閉域だけで接続するといったことは出来ませんので気をつけましょう。

物理的なネットワーク構成

Microsoft が世界中に保有するバックボーン ネットワークや、Azure データセンター内のネットワーク アーキテクチャについては、多少情報が古いものも混じってますが以下が参考になります。使用しているスイッチやルーターの名称まで記載されているものもあるので、インフラ野郎は隅から隅まで目を通すと興味深いかと思います。

# 以下、上記から拝借。

Microsoft 所有の Global Network の全体像。水色が自社所有、濃い青が借用、点線が計画中のもの。

 

Azure の各リージョンは Microsoft の Global Network (WAN) に接続され、世界中の Edge から Internet や ExpressRoute で接続されます。

 

各リージョンには複数のデータセンターがあり、RNG (Regional Network Gateway) で束ねられています。

 

データセンター内は、Quantum 10 (Q10) のアーキテクチャが採用され、以下の様な機器が使用されているらしいです。

VNET の仕組み

IaaS ユーザーの方からすると、先のような概念的な話よりも、Azure VNET の方が身近かと思います。

が、VNET の仕組みをきちんと理解した上で使っている人は少ないのではないかと思うので改めて。

 

Azure では、数百万台規模の物理サーバーが世界中に存在しています。VM はリージョン内のどこかの物理サーバー上でホストされますが、同一 VNET 内の VM 間の通信はどのように行われているかを考えるには、Azure 基板側のアンダーレイ ネットワークと、VNET 側のオーバーレイ ネットワークを意識する必要があります。

ここでは、以下の図のように 2 台の物理サーバー上に 2 つの VNET (A, B) が存在している場合を考えます。VNET A の 10.0.0.4 -> 10.0.0.5 宛に通信する場合は、物理サーバー上で一度カプセル化されてアンダーレイ ネットワーク上でルーティングされます。

# VNET A と B は論理的に分離されているので、別 VNET に同一の Private IP を持つ VM が乗っていても問題は起きません。

VFP の仕組み

こうした Azure の SDN を支えているのが、Hyper-V の Virtual Switch で動作する VFP (Virtual Filtering Platform) です。

詳しいことは Windows Server 2016 等の HNV 系のドキュメントや、Microsoft Research の論文を読むと理解が深まります。

論文内の画像を抜粋しつつ、かいつまんで説明すると、Hyper-V の仮想スイッチ上でフィルター ドライバーの用に振る舞い、Ingress / Egress のトラフィックに対しての処理を行うのが VFP です。

VFP ではどのような処理が行われるかというと、以下の図のように大きく 4 種類の処理があります。

  • VNET: 前述のアンダーレイ・オーバーレイ ネットワーク間のカプセル化 (encap / decap) を担います。
  • NAT: Public IP で受信したパケットを VNET 内の Private IP に変換したり、LB 経由の通信の NAT を担います。
  • ACLs: Network Security Group (NSG) の機能に該当するものです。
  • Metering: 各種メトリックのデータ取得を担います。課金メーターもこのレイヤーで行っています。

# ちなみに、上図の略称はそれぞれ以下の通り

  • PA: Physical Address (基盤側の IP アドレス)
  • CA: Customer Address (VNET 内の Private IP アドレス)
  • VIP: Virtual IP (Public IP のこと)
  • DIP: Dynamic IP (Private IP のこと)

 

VNET 内の通信を行う場合

では、もう少し噛み砕いて見てみましょう。(Metering は通信に直接関係しないので省略)

10.0.0.4 の VM からパケットが出て行く際は、10.0.0.4 -> 10.0.0.5 の通信として NIC および Subnet のNSG 送信規則で評価が行われます。その後カプセル化が行われ、送信元の物理サーバーの PA -> 宛先 IP の VM をホストする物理サーバーの PA (192.0.2.1 -> 192.0.2.2) のように Azure 基盤のネットワーク上をルーティングされます。

受信側ではカプセル化を解除するとともに、そのパケットが自身のホストするどの VM / VNET 宛なのかを判断し、Subnet および NIC の NSG で受信規則に基づいて評価を行います。

Azure VM 間で通信をする際、通常ここまで意識はしませんが、実は裏では VFP が頑張ってくれています。

 

VM の Public IP 宛の通信の場合 (LB 宛もほぼ同等)

続いて、Azure VM の Public IP 宛に通信が来た場合を考えてみます。

Internet 側からパケットが届きますが、VFP は Public IP と Private IP の対応を知っているため、宛先 IP を DNAT して VM に渡します。

反対に、戻りのパケットでは SNAT をして Src IP を Public IP に書き換えてから出ていきます。

なお、NSG の評価は受信方向の通信であれば Public IP や LB の NAT 処理後、送信方向の通信であれば NAT 処理前に行われるので、VM の Private IP のまま評価されます。

# たまに、Public IP 宛に届いた通信を NSG でブロックしようとする人がいますが、そんなことはできません。

 

UDR を設定した場合の挙動

次に、仮想アプライアンス (NVA) を構築する場合などで、全ての宛先 (0.0.0.0/0) 宛の通信を NVA へ向けるような UDR を設定した場合を考えてみます。

前述の 10.0.0.4 -> 10.0.0.5 宛の通信と似ていますが、送信元の物理サーバー上でカプセル化が行われる際、UDR を向けた NVA がホストされている物理サーバーの PA 宛として Azure 基盤側でルーティングが行われます。

この辺りは SDN 特有で、慣れないと混乱しますが、分からなくなったら落ち着いて図にするのが吉です。

Azure ネットワーク、ムズカシイネ。

 

その他、Azure のネットワークを理解するうえで参考になる資料


NSG / UDR の定義を CSV から生成する方法



NSG とか UDR に定義を追加するとき、CSV から一括でインポートしたいことありますよね。

昔作ったスクリプトが残ってたので、GitHub で適当に公開しておきました。

 

ご自由にどうぞ。

Add-AzureRmNetworkSecurityRuleConfigFromCSV.ps1

Add-AzureRmRouteConfigFromCSV.ps1


削除できなくなった Azure リソースを頑張って消す方法



Azure を使っていると、たまに設定ミス等でリソースが削除できない状態に陥ることがあります。

そんな時は、ひとまず以下を試してみると消せる場合があるのでご参考までにどうぞ。(必ず消せるとは限りません)

1. Azure PowerShell で正しい値に設定しなおす

誤った設定を流し込んで、リソースの状態が「失敗」や「Provisioning State: Failed」 になっている場合、Azure PowerShell 等で正しい構成情報で上書きすることで解消できることが多々あります。

一度 Azure PowerShell で既存の設定を Get して、誤ったパラメーターを修正したのち、再度 Set してみましょう。

# 誤った設定をして、「失敗」状態になった例

# Azure PowerShell で設定を修正する例 (ExpressRoute の接続リソースの例)

# 既存の設定を取得
$Connection = Get-AzureRmVirtualNetworkGatewayConnection -Name shuda1120 -ResourceGroupName shudaExR

# 誤った設定箇所を修正
$Connection.Peer.Id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/ExR/providers/Microsoft.Network/expressRouteCircuits/MyCircuit"

# 修正後の設定で上書き
Set-AzureRmVirtualNetworkGatewayConnection -VirtualNetworkGatewayConnection $Connection

2. Resource Explorer で正しい値に設定しなおす

Azure PowerShell と同じような話ですが、Resource Explorer (https://resources.azure.com) でも JSON の書き換えが出来たりします。

左のメニューから対象のサブスクリプション内のリソースを辿っていって、対象のリソースの [Edit] から書き換えて [PUT] しましょう。

# Resource Explorer から修正する例

3. JSON テンプレートの完全デプロイを試す

Azure は、JSON テンプレートからリソースをデプロイできますが、増分 (差分) モードと完全モードがあるのをご存知でしょうか。

完全デプロイをすると、対象のリソース グループ内を JSON テンプレートの内容で完全に上書きすることができます。

つまり、既存のリソースは削除されるので、それを利用して無理やり消すという小技が使える場合があります。

(不用意に使うと、他のリソースが消えるので十分注意しましょう)

4. サポートに依頼する

パッと思いつくのは以上 3 点なので、ダメそうであればサポートに依頼しましょう。

ただし、サポートの中の人もお客様環境を直接操作したりできる権限は基本的に持っていないので (というか、持っていたら色々マズい)

修正が完了するにはエスカレーション等で少なくとも数日はかかります。気長に待ちましょう。


Windows Server 2019 で Windows Admin Center のポップアップを無効化する



Windows Server 2019 の起動時 (というか、サーバー マネージャーの起動時) に Windows Admin Center (WAC) のポップアップ [Windows Admin Center でのサーバー管理を試してみる] が出ますが、以下のレジストリで無効化できそうでした。

HKLM\SOFTWARE\Microsoft\ServerManager\DoNotPopWACConsoleAtSMLaunch

  • 0: サーバー マネージャー起動時に WAC のポップアップを表示 (既定)
  • 1: サーバー マネージャー起動時に WAC のポップアップを無効化

そもそもサーバー マネージャー自体を毎回起動させたくない場合は以下も一緒に設定しましょう。

HKLM\SOFTWARE\Microsoft\ServerManager\DoNotOpenServerManagerAtLogon

  • 0: ログイン時にサーバー マネージャーを起動 (既定)
  • 1: ログイン時にサーバー マネージャーを起動しない

 

Procmon で RegSetValue してるのを探すだけだから簡単ですね。

 

コマンドでやりたい場合は以下でいけるかな。

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager" /v DoNotPopWACConsoleAtSMLaunch /t REG_DWORD /d 1 /f
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager" /v DoNotOpenServerManagerAtLogon /t REG_DWORD /d 1 /f

 

ちなみに、Windows Admin Center 自体は非常に良いものなので、ぜひ使ってみてくださいな。

指崎さんのスライドがわかりやすいのでオススメです。

 

 

 

 


ログオンの監査の話



クラウドの時代になって、ポチポチするだけで Public IP を持った VM が手軽に作れる時代になりましたが、その一方で Public IP で直接アクセスできるの怖いなぁと思う話を先日きいたので、注意喚起の意味も込めてブログのネタにしてみるなど。

 

以下は至って普通の Windows VM ですが、[Event Viewer] – [Windows Logs] – [Security] から、”Audit Failure” でフィルターすると、AdminXXX とか、UserXXX とか、SUPPORT とか、ありがちなユーザー名で謎の IP からログインが多数試行されてたりします。

 

Details の中身をよく見てみると、どういうユーザー名で (TargetUserName)、どういうアクセス方法で (LogonType)、どこから (IpAddress) アクセスがあったかがわかります。詳しくは以下のドキュメントとか見てもらえればと思いますが、RDP の場合には LogonType は 10 とかで記録されて、その他ネットワーク越しのアクセスだと 3 とかが多いかな。

で、アクセス元の IP を適当に調べてみると、上記の例ではロシアからのアクセスで、既に複数の Abuse (迷惑行為の報告) が上がってるみたいですね。

まあ、Failure なのでログオンされてはいないはずですが、調べてみると結構な数のログインが試行されているので、初めて見たときは結構な衝撃を受けると思います。脆弱なユーザー名・パスワードを使ってると、デプロイして数時間や数日で乗っ取られて攻撃元にされたり、その結果として自分自身が加害者側として報告される可能性もあるので、Firewall で特定の IP 以外からはブロックするとか、VPN 越しに Private IP でしか接続できなくするとか、オンプレ・クラウド問わず気を付けましょう。

あと、逆に攻撃された場合は当該 IP の管理者へも報告するといいと思います。(Microsoft 所有の IP の場合は以下から報告できます)

クラウドだと Azure も AWS も Public IP Range は公開されてますし、それに限らず我が家のコンテナ データセンターで使ってるグローバル IP アドレスなんかも普通にログイン試行されてる形跡があったりします。

手軽に検証環境とか作っちゃいがちですけど、IaaS の場合は OS やミドルウェアの管理はユーザーの責任範囲になるので、ユーザーとパスワードの管理をはじめ、セキュリティ対策には十分に気を付けましょうね、というお話でした。