Azureのネットワークの基本概念である「仮想ネットワーク」と「サブネット」の考え方についてまとめます。Azureでは「仮想ネットワーク」の中に複数の「サブネット」を設ける事ができます。同一の「仮想ネットワーク」に属する「サブネット」同士は互いにルーティングできる状態になっています。
前提
公式ドキュメント
参考になる公式ドキュメントを以下に示します。
- チュートリアル: Azure portal を使用してネットワーク セキュリティ グループでネットワーク トラフィックをフィルター処理する
- クイック スタート:仮想マシン ネットワーク トラフィック フィルターの問題を診断する
- Azure CLI を使用したネットワーク セキュリティ グループ フローのログの構成
事前設定
以下、リソースグループを作成します。
az group create --name MyResourceGroup --location japaneast
仮想ネットワーク内にサブネットを2つ作成します。
az network vnet create \ --resource-group MyResourceGroup \ --name Vnet01 \ --address-prefix 172.16.0.0/16 az network vnet subnet create \ --resource-group MyResourceGroup \ --name SubnetWeb \ --vnet-name Vnet01 \ --address-prefixes 172.16.1.0/24 az network vnet subnet create \ --resource-group MyResourceGroup \ --name SubnetDb \ --vnet-name Vnet01 \ --address-prefixes 172.16.2.0/24
セキュリティグループ
Webサーバのセキュリティグループ実装例
セキュリティグループの作成
以下のコマンドでセキュリティグループを作成します。
az network nsg create \ --resource-group MyResourceGroup \ --name NsgWeb
ssh(tcp22)とhttp(tcp80)を許可します。ssh(tcp22)は特定の拠点からの接続のみを許可するように送信元IPアドレスで絞り込みます。送信元IPアドレスは環境に応じて適宜の変更をお願いします。
引数priorityは評価順です。数値の小さいものが優先されます。他のファイアウォール製品ではsequence numberと呼称される事の方が多いでしょう。
az network nsg rule create \ --resource-group MyResourceGroup \ --nsg-name NsgWeb \ --name tcp22 \ --priority 100 \ --destination-port-ranges 22 \ --source-address-prefixes 103.5.140.135/32 \ --access Allow \ --protocol Tcp az network nsg rule create \ --resource-group MyResourceGroup \ --nsg-name NsgWeb \ --name tcp80 \ --priority 110 \ --destination-port-ranges 80 \ --access Allow \ --protocol Tcp
セキュリティグループの設定確認
showコマンドによる確認例は以下の通りです。queryで整形していますが、必要とされる情報は運用要件依存かと思いますので、queryの整形は適宜の変更が必要です。
$ az network nsg rule list \ --resource-group MyResourceGroup \ --nsg-name NsgWeb \ --query "[].{seq:priority, source:sourceAddressPrefix, port:destinationPortRange, action:access}" \ --output table Seq Source Port Action ----- ---------------- ------ -------- 100 103.5.140.135/32 22 Allow 110 * 80 Allow
azコマンドだけなく、ポータル(GUI)でも設定を確認してみましょう。「すべてのサービス」から辿る場合は、「ネットワーキング」「ネットワーク セキュリティ グループ」「ネットワーク セキュリティ グループ名(NsgWeb)」「受信セキュリティ規則」の順に押下します。すると、「AllowVnetInBound」「AllowAzureLoadBalancerInBound」という暗黙の許可設定がある事が分かります。Azure内の仮想マシンやロードバランサからは明示的な許可なしに接続可能な事が分かります。
暗黙的なルール含めて確認するには「az network nic list-effective-nsg」というコマンドを使用します。
疎通確認用の仮想マシン作成
疎通確認用の仮想マシンを作成します。
az vm create \ --resource-group MyResourceGroup \ --name LinuxWeb010 \ --image UbuntuLTS \ --size Standard_B1s \ --admin-username azureuser \ --ssh-key-values ~/.ssh/authorized_keys \ --vnet-name Vnet01 \ --subnet SubnetWeb \ --nsg NsgWeb \ --private-ip-address 172.16.1.10
Webサーバを模擬するために、nginxをインストールします。
az vm run-command invoke \ --resource-group MyResourceGroup \ --name LinuxWeb010 \ --command-id RunShellScript \ --scripts 'apt install -y nginx'
疎通確認
仮想マシン作成時のログから、仮想マシンに割り当てられたグローバルIPアドレスを判断します。
$ az vm create \ --resource-group MyResourceGroup \ --name LinuxWeb010 \ --image UbuntuLTS \ --size Standard_B1s \ --admin-username azureuser \ --ssh-key-values ~/.ssh/authorized_keys \ --vnet-name Vnet01 \ --tags uinitTest=nsg \ --subnet SubnetWeb \ --nsg NsgWeb \ --private-ip-address 172.16.1.10 It is recommended to use parameter "--public-ip-sku Standard" to create new VM with Standard public IP. Please note that the default public IP used for VM creation will be changed from Basic to Standard in the future. { "fqdns": "", "id": "/subscriptions/2e2f81a9-b030-410f-9784-c582580c932e/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/LinuxWeb010", "location": "japaneast", "macAddress": "00-22-48-68-D1-37", "powerState": "VM running", "privateIpAddress": "172.16.1.10", "publicIpAddress": "20.222.51.151", "resourceGroup": "MyResourceGroup", "zones": "" }
仮想マシンへのsshとhttpが成功する事を確認します。
admin@mac19 ~ % curl -I http://20.222.51.151/ HTTP/1.1 200 OK Server: nginx/1.14.0 (Ubuntu) Date: Sun, 27 Mar 2022 05:26:44 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Sun, 27 Mar 2022 05:23:10 GMT Connection: keep-alive ETag: "623ff4be-264" Accept-Ranges: bytes admin@mac19 ~ % admin@mac19 ~ % admin@mac19 ~ % admin@mac19 ~ % ssh azureuser@20.222.51.151 <omitted> Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. To run a command as administrator (user "root"), use "sudo <command>". See "man sudo_root" for details. azureuser@LinuxWeb010:~$
DBサーバのセキュリティグループ実装例
セキュリティグループの作成
以下のコマンドでセキュリティグループを作成します。
az network nsg create \ --resource-group MyResourceGroup \ --name NsgDB
mysql(tcp3306)を許可し、さらに他のサーバからの一切のログインを拒否します。まずはmysql(tcp3306)を許可する設定例を示します。
az network nsg rule create \ --resource-group MyResourceGroup \ --nsg-name NsgDB \ --name tcp3306 \ --priority 100 \ --destination-port-ranges 3306 \ --access Allow \ --protocol Tcp
ネットワークセキュリティグループは、デフォルトでAzure内の仮想マシンなどからの接続を許可する暗黙的な設定が入っています。この挙動を打ち消すには、明示的な拒否の設定が必要です。他のサーバからの一切のログインを拒否しますには、以下のような設定をします。
引数destination-port-rangesを省略するとデフォルト値80が設定される珍しい仕様になっていますので、全てのポート番号を指定する場合は以下のように明示的に「*」を指定してください。
az network nsg rule create \ --resource-group MyResourceGroup \ --nsg-name NsgDB \ --name denyAny \ --priority 4000 \ --destination-port-ranges '*' \ --access Deny \ --protocol '*'
セキュリティグループの設定確認
showコマンドによる確認例は以下の通りです。
$ az network nsg rule list \ --resource-group MyResourceGroup \ --nsg-name NsgDB \ --query "[].{seq:priority, source:sourceAddressPrefix, port:destinationPortRange, action:access}" \ --output table Seq Source Port Action ----- -------- ------ -------- 100 * 3306 Allow 4000 * * Deny
疎通確認用の仮想マシン作成
疎通確認用の仮想マシンを作成します。
az vm create \ --resource-group MyResourceGroup \ --name LinuxDb010 \ --image UbuntuLTS \ --size Standard_B1s \ --admin-username azureuser \ --ssh-key-values ~/.ssh/authorized_keys \ --vnet-name Vnet01 \ --subnet SubnetDb \ --nsg NsgDB \ --private-ip-address 172.16.2.10
MySQLを疑似するために、tcp3306をlisten状態にするスクリプトを仕込みます。
RDBMS固有の製品知識がなくても動作確認ができるよう、敢えて、ncコマンドを使用する手法を採用しています。
az vm run-command invoke \ --resource-group MyResourceGroup \ --name LinuxDb010 \ --command-id RunShellScript \ --scripts @/dev/stdin << EOF #!/bin/bash function loop_nc { while true ; do nc -l 3306 done } export -f loop_nc nohup /bin/bash -c loop_nc > /root/loop_nc.log 2>&1 & EOF
疎通確認
azureuser@LinuxWeb010:~$ nc 172.16.2.10 3306 A test message was sent to your server ^C azureuser@LinuxWeb010:~$
azureuser@LinuxWeb010:~$ ping 172.16.2.10 -c 3
PING 172.16.2.10 (172.16.2.10) 56(84) bytes of data.
— 172.16.2.10 ping statistics —
3 packets transmitted, 0 received, 100% packet loss, time 2055ms
azureuser@LinuxWeb010:~$
azureuser@LinuxWeb010:~$
azureuser@LinuxWeb010:~$ ssh 172.16.2.10
ssh: connect to host 172.16.2.10 port 22: Connection timed out
azureuser@LinuxWeb010:~$
補足
effective nsg
以下のようなコマンドで実際に適用されるネットワークセキュリティグループを確認できます。
az network nic list-effective-nsg \ --resource-group <リソースグループ名> \ --name <仮想NIC名>
操作例は以下の通りです。ポータル(GUI)で出力される以上の細かな情報が出力されます。GUIで表示されない何らかの暗黙的な設定が疑われる場合は、このコマンドの出力を確認してみるのも良いでしょう。
理由は不明ですが(想像するにセキュリティ上の理由や国防上の理由など)、実は一部のグローバルアドレスとの接続が許可されていない等のポータル(GUI)からは読み取れない様々な暗黙的な仕様を確認する事ができます。
NIC_ID=$(az vm nic list \ --resource-group MyResourceGroup \ --vm-name LinuxWeb010 \ --query "[0].id" \ --output tsv ) NIC_NAME=$(az vm nic show \ --resource-group MyResourceGroup \ --vm-name LinuxWeb010 \ --nic ${NIC_ID} \ --query "name" \ --output tsv ) az network nic list-effective-nsg \ --resource-group MyResourceGroup \ --name ${NIC_NAME} { "nextLink": null, "value": [ { "association": { "networkInterface": { "id": "/subscriptions/2e2f81a9-b030-410f-9784-c582580c932e/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkInterfaces/LinuxWeb010VMNic", "resourceGroup": "MyResourceGroup" }, "networkManager": null, "subnet": null }, <commit> "expandedDestinationAddressPrefix": [ "1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/9", "4.144.0.0/12", "4.160.0.0/11", "4.192.0.0/10", "5.0.0.0/8", "6.0.0.0/7", "8.0.0.0/7", <omitted>
トラフィックフィルターの診断
Inbound方向
ネットワーク ウォッチャーにはネットワークセキュリティグループの設定が想定通りか否かを診断するツールが備わっています。公式ドキュメント「クイック スタート:仮想マシン ネットワーク トラフィック フィルターの問題を診断する – Azure CLI」にはネットワーク ウォッチャーの有効化方法が記されていますが、殆どの場合は仮想マシンや仮想マシンスケールセットの作成と同時にネットワーク ウォッチャーが有効化されるので、意識する必要はない操作です。
さて、以下のようなコマンドを使用すると、トラフィックが許可されるのか拒否されるのか、どのようなセキュリティルールにヒットするのかを確認できます。
az network watcher test-ip-flow \ --resource-group <リソースグループ名> \ --direction <通信方向> \ --protocol <プロトコル> \ --local <ローカルIPアドレス>:<ローカルポート番号> \ --remote <リモートIPアドレス>:<リモートポート番号> \ --vm <仮想マシン名> \ --nic <仮想NIC名>
例えば、LinuxWeb010がssh(tcp22)を許可している事を確認するには、以下のように操作します。
$ az network watcher test-ip-flow \ --resource-group MyResourceGroup \ --direction Inbound \ --protocol TCP \ --local 172.16.1.10:22 \ --remote 103.5.140.135:60000 \ --vm LinuxWeb010 { "access": "Allow", "ruleId": "/subscriptions/2e2f81a9-b030-410f-9784-c582580c932e/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkSecurityGroups/NsgWeb/securityRules/tcp22", "ruleName": "securityRules/tcp22" }
LinuxDb010がssh(tcp22)を拒否している事を確認するには、以下のように操作します。
$ az network watcher test-ip-flow \ --resource-group MyResourceGroup \ --direction Inbound \ --protocol TCP \ --local 172.16.2.10:22 \ --remote 103.5.140.135:60000 \ --vm LinuxDb010 { "access": "Deny", "ruleId": "/subscriptions/2e2f81a9-b030-410f-9784-c582580c932e/resourceGroups/MyResourceGroup/providers/Microsoft.Network/networkSecurityGroups/NsgDB/securityRules/denyAny", "ruleName": "securityRules/denyAny" }
Outbound
このページでは説明を省略していますが、セキュリティグループはOutbound方向にも設定する事ができます。Outbound方向に設定したセキュリティグループが想定通りかも確認できます。例えば、LinuxWeb010からbing.com(13.107.21.200)へhttp(tcp80)の疎通が可能かどうかを確認するのは、以下のような操作になります。
$ az network watcher test-ip-flow \ --resource-group MyResourceGroup \ --direction Outbound \ --protocol TCP \ --local 172.16.1.10:60000 \ --remote 13.107.21.200:80 \ --vm LinuxWeb010 { "access": "Allow", "ruleId": "", "ruleName": "defaultSecurityRules/AllowInternetOutBound" }
NSGフローログ
NSGフローログを使用するには、Microsoft.Insightsを登録する必要があります。登録しているかどうか不明な場合は、以下のコマンドを実行します。
az provider register --namespace Microsoft.Insights
フローログを格納するストレージアカウントを作成します。すでにストレージアカウントが存在するならば、既存の物を利用しても良いでしょう。
az storage account create \ --name storagegokatei01 \ --resource-group MyResourceGroup \ --location japaneast \ --sku Standard_LRS
以下のようなコマンドでNSGフローログを有効にします。フローログはversion 1とversion 2があります。version 1の操作例は「Azure CLI を使用したネットワーク セキュリティ グループ フローのログの構成」を参照ください。
az network watcher flow-log create \ --resource-group MyResourceGroup \ --name flowLogWeb \ --enabled true \ --nsg NsgWeb \ --storage-account storagegokatei01 \ --location japaneast \ --format JSON \ --log-version 2
動作確認用のログを生成するために、LinuxWeb010に対して何らかの通信を発生させます。
curl -I http://20.222.51.151/ curl -I http://20.222.51.151:8080/ ssh azureuser@20.222.51.151
ログはinsights-logs-networksecuritygroupfloweventという名前のBLOBコンテナーに格納されます。コンテナからのダウンロード方法はAzure Storage Explorer, ポータル(GUI), CLIなど任意の方法で差し支えございません。
もし、ポータル(GUI)でダウンロードする場合は、「すべてのメニュー」から「ストレージ」「ストレージアカウント」「ストレージアカウント名(storagegokatei01)」「コンテナー」「insights-logs-networksecuritygroupflowevent」の順に画面遷移します。
日付やMacAddress毎にディレクトリが定義されていますので、ダウンロード対象となるJSONファイルを探します。JSONファイルは右クリックメニューでダウンロードできます。
ダウンロードしたJSONファイルは改行処理がなされておらず読みづらい状態になっていますので、jqコマンドなどを用いて適宜整形しながら読みます。
admin@mac19 ~ % cat PT1H.json | jq { "records": [ { "time": "2022-03-27T06:03:26.5437199Z", "systemId": "65afb951-d8ca-433f-b414-5b373bf61239", "macAddress": "00224868D137", "category": "NetworkSecurityGroupFlowEvent", "resourceId": "/SUBSCRIPTIONS/2E2F81A9-B030-410F-9784-C582580C932E/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/NSGWEB", "operationName": "NetworkSecurityGroupFlowEvents", "properties": { "Version": 2, "flows": [ { "rule": "DefaultRule_DenyAllInBound", "flows": [ { "mac": "00224868D137", "flowTuples": [ "1648360983,103.5.140.135,172.16.1.10,54656,8080,T,I,D,B,,,," ] } ] } ] } }, <omitted>