AzureのVNetに複数サブネットを設計する方法|Web層・DB層の分離とNSGによるアクセス制御をazコマンドで実践

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Azure > AzureのVNetに複数サブネットを設計する方法|Web層・DB層の分離とNSGによるアクセス制御をazコマンドで実践
「AzureのVNetにサブネットを複数切りたいが、CIDRをどう設計すればよいか分からない」「NSGをどのサブネットに割り当てれば意図した制御ができるのか自信が持てない」。こうした悩みはAzureを学び始めたLinuxエンジニアに非常によくある話です。

AWSのVPCを触った経験があれば、サブネット分割の考え方はそのまま通用します。AzureのVNetもパブリックサブネット・プライベートサブネットの分離が基本で、AWSのSecurity GroupにあたるものがAzureのNSG(Network Security Group)です。ただしAzureのNSGは、EC2インスタンスのように個別に紐付けるのではなく、サブネット単位またはNIC単位で割り当てる点が大きく異なります。

この記事では、AzureのVNetにWeb層(パブリック向け)とDB層(プライベート)の2つのサブネットを構築し、NSGでアクセスを制御するまでの実践手順を解説します。azコマンドによるCIDR設計・サブネット作成・NSGルール設定から動作確認・トラブルシュートまで順を追って説明します。

動作確認環境:Azure CLI 2.61.0、Ubuntu 24.04 LTS(Azure VMで検証済み)

この記事のポイント

・AzureのVNetはAWSのVPCと同概念。サブネット分離の設計思想は共通して使える
・NSGはサブネット単位で割り当てる。AWS SG(インスタンス単位)との最大の違い
・azコマンドでVNet・サブネット・NSGを作成し、ルールを設定する具体的な手順
・NSGルールが効かない時は「有効なセキュリティルール」コマンドで原因を特定する


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

なぜVNetにサブネットを分割するのか(AWSとの共通原則)

LinuxサーバーをAzureに移行する際、「VMを1つのサブネットに置けば動くのではないか」と思うかもしれません。技術的には正しいですが、本番環境ではWebサーバーとDBサーバーを同一サブネットに混在させるのは危険です。DBサーバーへのポートがインターネットから直接到達できる状態になるリスクがあるためです。

サブネットを分割してNSGで通信を制御することで、以下のメリットを得られます。

攻撃経路の最小化:Webサブネットへの侵入があっても、DBサブネットへの横断をNSGで阻止できます
権限の分離:サブネット単位でNSGを割り当てることで、ルールの適用範囲が明確になります
コンプライアンス対応:PCI-DSSやISO 27001などで要求されるネットワークセグメント分離を実装できます

AWSとの比較で言うと、以下のような対応関係になります。

概念 AWS Azure
仮想ネットワーク VPC VNet
サブネット Subnet Subnet
ファイアウォール(サブネット・NIC) Security Group NSG
サブネットレベルACL Network ACL NSG(同じNSGで兼用可)
インターネット経路 Internet Gateway デフォルトで付与(明示的に削除可)
AWSではNetwork ACLとSecurity Groupを使い分けますが、AzureではNSGをサブネットとNICの両方に割り当てることで同等の制御を実現できます。

CIDRを設計する(VNet・サブネットのアドレス計画)

実作業の前に、アドレス計画を決めておきます。後から変更すると影響範囲が大きいので、最初に整理することが重要です。

この記事では以下の構成を使います。

リソース CIDR 用途
VNet(rg-webapp-vnet) 10.10.0.0/16 全サブネットを含む仮想ネットワーク
web-subnet 10.10.1.0/24 Webサーバー(パブリック向け)
db-subnet 10.10.2.0/24 DBサーバー(プライベート・外部非公開)
VNetのCIDRは /16 として広く確保し、サブネットごとに /24 を割り当てます。将来的にApp層(10.10.3.0/24)や管理用サブネット(10.10.10.0/24)を追加できるよう余裕を持たせておくのが現場の鉄則です。

Azureのサブネットは、1ブロックにつき最初と最後の5つのIPアドレス(ネットワークアドレス・ゲートウェイ用・DNS用・放送用・予約)がAzureに予約されます。/24 の場合は 256 - 5 = 251 個のIPが使えます。

azコマンドでVNetと複数サブネットを作成する

1. リソースグループを確認する

まず作業対象のリソースグループを確認します。既存のものを使う場合はそのまま次のステップに進んでください。新規に作成する場合は以下のコマンドを実行します。

# リソースグループの作成(すでにある場合はスキップ) az group create \ --name rg-webapp \ --location japaneast

実行結果の例です。

{ "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-webapp", "location": "japaneast", "managedBy": null, "name": "rg-webapp", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups" }

`"provisioningState": "Succeeded"` が確認できればリソースグループの作成は完了です。

2. VNetを作成する(Webサブネット付き)

VNetを作成するとき、`--subnet-name` と `--subnet-prefix` を指定することで最初のサブネット(web-subnet)を同時に作成できます。

# VNetとwebサブネットを同時に作成する az network vnet create \ --resource-group rg-webapp \ --name rg-webapp-vnet \ --address-prefixes 10.10.0.0/16 \ --subnet-name web-subnet \ --subnet-prefixes 10.10.1.0/24 \ --location japaneast

実行結果の抜粋です。

{ "newVNet": { "addressSpace": { "addressPrefixes": [ "10.10.0.0/16" ] }, "location": "japaneast", "name": "rg-webapp-vnet", "provisioningState": "Succeeded", "subnets": [ { "addressPrefix": "10.10.1.0/24", "name": "web-subnet", "provisioningState": "Succeeded" } ] } }

3. DBサブネットを追加する

2つ目のサブネット(db-subnet)は `az network vnet subnet create` で追加します。

# DBサブネットを追加する az network vnet subnet create \ --resource-group rg-webapp \ --vnet-name rg-webapp-vnet \ --name db-subnet \ --address-prefixes 10.10.2.0/24

作成後、サブネットの一覧で確認します。

# サブネット一覧を確認する az network vnet subnet list \ --resource-group rg-webapp \ --vnet-name rg-webapp-vnet \ --output table

実行結果の例です。

Name AddressPrefix ProvisioningState ---------- --------------- ------------------- web-subnet 10.10.1.0/24 Succeeded db-subnet 10.10.2.0/24 Succeeded

2つのサブネットが `Succeeded` で確認できれば次のステップに進んでください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Azure対応セミナーの詳細を見る >>

NSGを作成してサブネットに割り当てる

NSG(Network Security Group)はAWSのSecurity Groupに相当するファイアウォールですが、Azureではサブネット単位で割り当てます。WebサブネットとDBサブネットに別々のNSGを作成し、それぞれ適切なルールを設定します。

1. WebサブネットのNSGを作成する

Webサブネット用のNSGを作成し、HTTPSとSSHのインバウンドを許可します。

# WebサブネットのNSGを作成する az network nsg create \ --resource-group rg-webapp \ --name nsg-web-subnet \ --location japaneast # HTTPS(443)のインバウンドを許可する az network nsg rule create \ --resource-group rg-webapp \ --nsg-name nsg-web-subnet \ --name allow-https \ --priority 100 \ --protocol Tcp \ --direction Inbound \ --source-address-prefixes Internet \ --destination-address-prefixes '*' \ --destination-port-ranges 443 \ --access Allow # SSH(22)のインバウンドを管理PCからのみ許可する az network nsg rule create \ --resource-group rg-webapp \ --nsg-name nsg-web-subnet \ --name allow-ssh-from-admin \ --priority 200 \ --protocol Tcp \ --direction Inbound \ --source-address-prefixes 203.0.113.0/24 \ --destination-address-prefixes '*' \ --destination-port-ranges 22 \ --access Allow

`--source-address-prefixes 203.0.113.0/24` の部分は自分のPCのグローバルIPアドレスまたはCIDRに置き換えてください。`Internet` と指定すればすべてのインターネットIPからのSSHを許可することになり危険です。

2. DBサブネットのNSGを作成する

DBサブネットはインターネットからのアクセスを全遮断し、Webサブネット(10.10.1.0/24)からのMySQL(3306)のみを許可します。

# DBサブネットのNSGを作成する az network nsg create \ --resource-group rg-webapp \ --name nsg-db-subnet \ --location japaneast # Webサブネットからのみ3306を許可する az network nsg rule create \ --resource-group rg-webapp \ --nsg-name nsg-db-subnet \ --name allow-mysql-from-web \ --priority 100 \ --protocol Tcp \ --direction Inbound \ --source-address-prefixes 10.10.1.0/24 \ --destination-address-prefixes '*' \ --destination-port-ranges 3306 \ --access Allow # インターネットからの全インバウンドを拒否する(優先度を高くする) az network nsg rule create \ --resource-group rg-webapp \ --nsg-name nsg-db-subnet \ --name deny-internet-inbound \ --priority 900 \ --protocol '*' \ --direction Inbound \ --source-address-prefixes Internet \ --destination-address-prefixes '*' \ --destination-port-ranges '*' \ --access Deny

NSGのルール評価は優先度(priority)の小さい番号から順に適用されます。優先度100のallow-mysql-from-webが先に評価されるため、Webサブネットからの3306は許可され、その後に優先度900のdeny-internet-inboundでインターネットからの通信を遮断できます。

3. NSGをサブネットに関連付ける

作成したNSGをそれぞれのサブネットに割り当てます。

# WebサブネットにNSGを割り当てる az network vnet subnet update \ --resource-group rg-webapp \ --vnet-name rg-webapp-vnet \ --name web-subnet \ --network-security-group nsg-web-subnet # DBサブネットにNSGを割り当てる az network vnet subnet update \ --resource-group rg-webapp \ --vnet-name rg-webapp-vnet \ --name db-subnet \ --network-security-group nsg-db-subnet

割り当て後、サブネットの詳細を確認します。

# web-subnetのNSG割り当てを確認する az network vnet subnet show \ --resource-group rg-webapp \ --vnet-name rg-webapp-vnet \ --name web-subnet \ --query "networkSecurityGroup.id" \ --output tsv

実行結果の例です。

/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-webapp/providers/Microsoft.Network/networkSecurityGroups/nsg-web-subnet

NSGのIDが返れば割り当てが完了しています。

動作確認(VMを配置してcurlとncで疎通をテストする)

各サブネットにLinux VM(Ubuntu 24.04)を配置して、NSGルールどおりにアクセス制御されているかを確認します。

WebサブネットのVMからDBサブネットのVMへ接続できることを確認し、逆方向(DBサブネット → Webサブネット)は3306への接続が拒否されることを確認します。

# WebサブネットのVMからDB VMへの3306接続テスト(許可されるはず) # DB VMのプライベートIPが 10.10.2.4 の場合 nc -zv 10.10.2.4 3306

接続が許可されている場合の出力例です(DB VMでMySQL/Mariadbは起動していないためreset表示になる場合もありますが、connectionは確立されます)。

Connection to 10.10.2.4 3306 port [tcp/mysql] succeeded!

次に、DBサブネットのVM(10.10.2.4)からWebサブネットのVM(10.10.1.4)への3306接続を試みます。NSGで拒否されるため接続が失敗するはずです。

# DBサブネットのVMからWebサブネットへの3306接続テスト(拒否されるはず) nc -zv 10.10.1.4 3306

nc: connect to 10.10.1.4 port 3306 (tcp) failed: Connection timed out

タイムアウトになれば意図したとおりNSGが機能しています。Webサブネット用のNSGにはDBサブネットからの3306インバウンドを許可するルールがないため、デフォルトの拒否ルール(65500:DenyAllInBound)が適用されています。

トラブルシュート(NSGルールが効かない時の調査手順)

「ルールを設定したはずなのに通信できない」「拒否しているつもりなのに通ってしまう」という時は、以下の手順で原因を特定します。

1. 有効なセキュリティルールを確認する

NICに実際に適用されているルールは、NSGをサブネット単位とNIC単位に二重で設定した場合に予想と異なる優先順位になることがあります。`az network nic list-effective-nsg` で実際に有効なルールを確認します。

# NIC名を確認する az network nic list \ --resource-group rg-webapp \ --query "[].{Name:name, Subnet:ipConfigurations[0].subnet.id}" \ --output table # 有効なNSGルールを確認する(NIC名を指定) az network nic list-effective-nsg \ --resource-group rg-webapp \ --name vm-web-nic \ --output table

NetworkSecurityGroup SecurityGroup Direction Priority Name ---------------------------- -------------------- ----------- ---------- --------------------- nsg-web-subnet nsg-web-subnet Inbound 100 allow-https nsg-web-subnet nsg-web-subnet Inbound 200 allow-ssh-from-admin nsg-web-subnet nsg-web-subnet Inbound 65000 AllowVnetInBound nsg-web-subnet nsg-web-subnet Inbound 65500 DenyAllInBound

2. NSGルールの設定ミスを確認する

よくあるミスとして以下の点を確認してください。

送信元IPのタイプミス:`10.10.1.0/24` と指定すべきところを `10.10.1.1/24` と書いてしまうパターン
優先順位の重複:同じ優先度の番号を別のルールに使うとエラーになります
プロトコルの不一致:TCP専用のポート(3306)にプロトコルを `*`(TCP+UDP)で設定すると想定外のUDPも許可されます
アウトバウンドの見落とし:インバウンドを許可しても、送信元VM側のアウトバウンドNSGが拒否していると通信が成立しません

# NSGルール一覧を優先順位付きで確認する az network nsg rule list \ --resource-group rg-webapp \ --nsg-name nsg-db-subnet \ --query "[].{priority:priority, name:name, access:access, direction:direction, srcAddr:sourceAddressPrefix, dstPort:destinationPortRange}" \ --output table

Priority Name Access Direction SrcAddr DstPort ---------- ----------------------- -------- ----------- --------------- --------- 100 allow-mysql-from-web Allow Inbound 10.10.1.0/24 3306 900 deny-internet-inbound Deny Inbound Internet *

まとめ

AzureのVNetに複数サブネットを設計してNSGでアクセスを制御する手順をまとめます。
やりたいこと コマンド
VNetとサブネットを同時作成する az network vnet create --subnet-name ... --subnet-prefixes ...
サブネットを追加する az network vnet subnet create --vnet-name ... --address-prefixes ...
サブネット一覧を確認する az network vnet subnet list --output table
NSGを作成する az network nsg create --name ...
NSGにルールを追加する az network nsg rule create --priority ... --access Allow/Deny
NSGをサブネットに割り当てる az network vnet subnet update --network-security-group ...
実効NSGルールを確認する az network nic list-effective-nsg --name ...
AWSのVPCを使ったことがあるエンジニアであれば、サブネット分割とファイアウォールルールの考え方はほぼ同じです。AzureではNSGをサブネット単位で割り当てる点と、優先度の数値が小さいほど先に評価される点を押さえておけば、迷わずネットワーク設計を進められます。Linux ポート確認の全コマンドを参照して、VM内のポート疎通確認とあわせて動作検証することをおすすめします。

サブネット設計の基礎が固まったら、次はNATゲートウェイを追加してDBサブネットのアウトバウンド経路を制御したり、Bastionを導入してSSHのパブリックIP露出をなくすなど、セキュリティ強化を段階的に進めてください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Azure対応セミナーの詳細を見る >>

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

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

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

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

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

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

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

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

この記事を書いた人

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

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

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