0. 背景

Azure VMを使う時に筆者はいつもめんどくさがってVM作成時にオプションを使いVnet・Subnet・NSGを作成していた。しかしそれがベストプラクティスに沿っていないこと最近知ったため備忘録として残しておこうと思ったため。

1. 結論

VNet・Subnet・NSGは、VM作成前に個別に作成してからアタッチするべき


2. 今回立てたいVM構成

以下の構成を前提として検証を行う

Resource Group: rg-example
Region: Japan East

VNet:    vnet-example       (10.0.0.0/16)
  └── Subnet: snet-example  (10.0.0.0/24)
        └── NSG: nsg-example
              └── Inbound Rule: SSH(22) - 自分のIPのみ許可

VM:      vm-example
  OS:    Ubuntu 24.04 LTS
  NIC:   自動作成
  Public IP: pip-example

構成図

Internet
   │
   │ SSH(22) ← 自分のIPのみ
   │
Public IP (pip-example)
   │
  NIC
   │
  VM (vm-example / Ubuntu 24.04 LTS)
   │
Subnet (snet-example: 10.0.0.0/24)
   │
NSG (nsg-example) ← Subnetレベルでアタッチ
   │
VNet (vnet-example: 10.0.0.0/16)

3. ベストプラクティスな立て方の手順

以下の順番でリソースを作成する。前提として作業は全てAzure Portalで行うこととしている。

① Resource Group
② VNet + Subnet
③ NSG → ルール設定 → Subnetにアタッチ
④ Public IP
⑤ VM(既存のSubnetを指定)

① Resource Groupの作成

  1. Azure Portal上部の検索バーで「リソース グループ」を検索し選択
  2. 「作成」をクリック
  3. 以下を入力して「確認および作成」→「作成」
項目
サブスクリプション任意
リソース グループ名rg-example
リージョンJapan East

② VNet + Subnetの作成

  1. 検索バーで「仮想ネットワーク」を検索し選択
  2. 「作成」をクリック
  3. 「基本」タブで以下を入力
項目
リソース グループrg-example
名前vnet-example
リージョンJapan East
  1. 「IPアドレス」タブで以下を設定
項目
IPv4 アドレス空間10.0.0.0/16
サブネット名snet-example
サブネット アドレス範囲10.0.0.0/24
  1. 「確認および作成」→「作成」

③ NSGの作成・ルール設定・Subnetへのアタッチ

  1. 検索バーで「ネットワーク セキュリティ グループ」を検索し選択
  2. 「作成」をクリック
  3. 以下を入力して「確認および作成」→「作成」
項目
リソース グループrg-example
名前nsg-example
リージョンJapan East
  1. 作成した nsg-example を開く
  2. 左メニューの「受信セキュリティ規則」→「追加」をクリック
  3. 以下を入力して「追加」
項目
ソースIP アドレス
ソースIPアドレス自分のグローバルIPアドレス(例: 203.0.113.10/32
宛先ポート範囲22
プロトコルTCP
アクション許可
優先度100
名前Allow-SSH-MyIP
補足: 自分のグローバルIPは https://whatismyip.com などで確認できる。末尾の /32 はそのIPアドレス1つだけを指定する意味。
  1. nsg-example の左メニューから「サブネット」→「関連付け」をクリック
  2. 以下を選択して「OK」
項目
仮想ネットワークvnet-example
サブネットsnet-example

④ Public IPの作成

  1. 検索バーで「パブリック IP アドレス」を検索し選択
  2. 「作成」をクリック
  3. 以下を入力して「確認および作成」→「作成」
項目
リソース グループrg-example
名前pip-example
リージョンJapan East
SKUStandard
割り当て静的

⑤ VMの作成(既存リソースを指定)

  1. 検索バーで「仮想マシン」を検索し選択
  2. 「作成」→「Azure仮想マシン」をクリック
項目
リソース グループrg-example
仮想マシン名vm-example
リージョンJapan East
イメージUbuntu Server 24.04 LTS
認証の種類SSH 公開キー(推奨)
項目
仮想ネットワークvnet-example(既存を選択)
サブネットsnet-example(既存を選択)
パブリック IPpip-example(既存を選択)
NIC ネットワーク セキュリティ グループなし
ポイント: NSGはSubnetレベルで既にアタッチ済みのため、NICレベルのNSGは「なし」に設定する。NICとSubnetの両方にNSGをアタッチすると二重管理になり、ルールの把握が困難になる。
  1. 「確認および作成」→「作成」

4. VMでまとめて作成した場合の手順と出来上がる構成

手順

VM作成画面の「ネットワーク」タブで各項目を「新規作成」のままにするだけで、VNet・Subnet・NSGが自動で作成される。

項目自動生成される値
仮想ネットワークvm-example-vnet
サブネットdefault
パブリック IPvm-example-ip
NSGvm-example-nsg

出来上がる構成

Resource Group: rg-example
│
├── vm-example           (VM)
├── vm-example_disk1     (OS Disk)
├── vm-example928        (NIC)
├── vm-example-ip        (Public IP)
├── vm-example-nsg       (NSG) ← NICレベルにアタッチ
└── vm-example-vnet      (VNet)
      └── Subnet: default (10.0.0.0/24)
            └── NSGアタッチ: なし

構成図

Internet
   │
   │ SSH(22)   ← Any(インターネット全開放)
   │ RDP(3389) ← Any(インターネット全開放)
   │
Public IP (vm-example-ip)
   │
NIC ──── vm-example-nsg(NSGがNICレベルに紐付き)
   │
VM (vm-example / Ubuntu 24.04 LTS)
   │
Subnet (default: 10.0.0.0/24) ← NSGなし
   │
VNet (vm-example-vnet: 10.0.0.0/16)

5. 問題点

まとめて作成した場合に発生する問題を、ベストプラクティスの構成と対比して説明する。


問題① NSGがNICレベルにアタッチされている

まとめて作成ベストプラクティス
NSGのアタッチ先NIC(VMごと)Subnet(共通)
複数VM追加時VMごとにNSGが増殖SubnetのNSG1つで制御

NICレベルのNSGはそのVM専用の設定になる。同じSubnetに2台目のVMを追加したとき、同じルールを持つNSGをもう1つ作ることになり、管理箇所が分散する。

【例:まとめて作成した場合に2台目を追加したケース】

Subnet (default)
  ├── vm-example  ──── vm-example-nsg  (SSH: Any許可)
  └── vm-example2 ──── vm-example2-nsg (SSH: Any許可) ← 同じ設定のNSGが増殖

【ベストプラクティスの場合】

Subnet (snet-example) ──── nsg-example (SSH: 自分のIPのみ)
  ├── vm-example
  └── vm-example2  ← SubnetのNSGで一元管理

問題② SSH・RDPがデフォルトで全開放されている

まとめて作成すると、NSGに以下のルールが自動生成される。

Inbound Rules(自動生成)
┌─────────────┬──────────┬────────┐
│ Source      │ Port     │ Action │
├─────────────┼──────────┼────────┤
│ Any         │ 22 (SSH) │ Allow  │ ← インターネット全開放
│ Any         │ 3389(RDP)│ Allow  │ ← インターネット全開放
└─────────────┴──────────┴────────┘

インターネット上の不特定多数からSSHの接続試行が行われ、ブルートフォース攻撃の対象になる。

ベストプラクティスでは接続元IPを自分のIPのみに限定する。

Inbound Rules(ベストプラクティス)
┌──────────────────┬──────────┬────────┐
│ Source           │ Port     │ Action │
├──────────────────┼──────────┼────────┤
│ 203.0.113.10/32  │ 22 (SSH) │ Allow  │ ← 自分のIPのみ
└──────────────────┴──────────┴────────┘

問題③ VM名に依存した命名になる

自動生成されるリソース名はすべてVM名を冠する。

vm-example-vnet   ← ネットワークリソースなのにVM名が入っている
vm-example-nsg
vm-example-ip

ネットワークリソースはVMと独立して存在するべきものだが、名前がVMに紐付いてしまうため、後から構成を拡張する際に命名規則が崩れる。


問題④ VM削除時にネットワーク設定を誤って削除するリスク

まとめて作成するとすべてのリソースが同一Resource Groupに混在し、それぞれの依存関係が不明確になる。VMを削除しようとした際に、VNetやNSGまで一緒に削除してしまうミスが起きやすい。

事前に個別作成しておけば、「ネットワークリソースはVMとは別管理」という意識が構造として表れ、誤削除を防ぎやすくなる。

観点まとめて作成事前に個別作成(ベストプラクティス)
NSGのアタッチ先NICレベル(VM専用)Subnetレベル(共通管理)
SSH接続元Any(全開放)自分のIPのみ
リソースの命名VM名に依存役割ベースで独立
複数VM追加時NSGが増殖・管理分散SubnetのNSGで一元管理
VM削除時のリスクネットワーク設定も消す恐れあり独立しているため安全
PoC・検証用途許容範囲推奨だが過剰な場合もある

6. まとめ