Azure NSG(ネットワークセキュリティグループ)入門!ゼロトラストを実現する設定と使い方
生徒
「Azureでサーバーを作ったのですが、外部からのアクセスを制限したり、特定の通信だけを許可したりするにはどうすればいいですか?」
先生
「Azureでは、NSG(Network Security Group:ネットワークセキュリティグループ)という機能を使って通信を制御します。これは仮想のファイアウォールのような役割を果たすんですよ。」
生徒
「ファイアウォールですね!設定は難しいのでしょうか?」
先生
「ルールを順番に適用する仕組みさえ覚えれば、初心者の方でも大丈夫です。最近流行りの『ゼロトラスト』という、何も信頼せずにすべてを検証するセキュリティの考え方を実現する上でも非常に重要な項目です。一緒に詳しく見ていきましょう!」
1. Azure NSGとは?基本概念と役割を解説
Azure(アジュール)を利用する上で避けて通れないのが、Azure NSG(Network Security Group / ネットワーク セキュリティ グループ)です。NSGは、Azure上の仮想ネットワーク(Virtual Network / VNet)内にあるリソースに対して、ネットワークトラフィック(通信の流れ)を許可または拒否するための「関所」や「フィルター」の役割を果たします。
具体的には、IPアドレス、ポート番号、プロトコル(TCP/UDPなど)に基づいて、どの通信を通し、どの通信をブロックするかを細かく設定できます。昨今のクラウドセキュリティでは、外部ネットワークだけでなく内部ネットワークも信頼しないゼロトラスト(Zero Trust)という考え方が主流です。NSGはこのゼロトラストを実現するための最小単位の防御壁となります。
例えば、Webサーバーであれば「インターネットからの80番ポート(HTTP)や443番ポート(HTTPS)は許可するけれど、保守用の22番ポート(SSH)は自分の家のIPアドレスからしか許可しない」といった制御が可能です。これにより、悪意のある第三者からの不正アクセスを防ぐことができます。
2. NSGの仕組み:インバウンドとアウトバウンドの違い
NSGを設定する際には、通信の方向に注目する必要があります。方向には「インバウンド」と「アウトバウンド」の2種類があります。読み方はそれぞれインバウンド(Inbound)、アウトバウンド(Outbound)です。
インバウンド規則(受信規則)は、外部からリソース(仮想マシンなど)に入ってくる通信を制御します。例えば、外からWebサイトを見に来るユーザーのアクセスを許可する設定はこちらで行います。一方、アウトバウンド規則(送信規則)は、リソースから外部へ出ていく通信を制御します。例えば、サーバーが自動アップデートのために外部のサイトにアクセスするのを許可したり、逆に情報漏洩を防ぐために特定の場所以外への通信を禁止したりする場合に使用します。
NSGのルールには優先順位(Priority)があり、100から4096までの数字で指定します。数字が小さいほど優先度が高く、先に評価されます。一度ルールに合致すると、それ以降のルールは評価されません。この「早い者勝ち」のルールを理解することが、設定ミスを防ぐ最大のポイントです。
3. ゼロトラストセキュリティとNSGの深い関係
ゼロトラストとは、直訳すると「何も信頼しない」という意味です。従来の境界型セキュリティでは「社内ネットワークの中は安全」と考えていましたが、現代では「ネットワークのどこにいても脅威は存在する」と仮定します。Azure NSGは、このゼロトラストの原則である「最小特権の原則」を適用するのに最適なツールです。
具体的には、まず全ての通信を拒否するように設定し、そこから業務に必要な通信だけを一つずつ許可していく「ホワイトリスト形式」での運用が推奨されます。AzureのNSGには最初から「既定のルール」が含まれており、安全のために一部の通信が最初から許可されていますが、より強固なセキュリティを目指すなら、これらを理解した上で独自のルールを追加していく必要があります。
4. 仮想マシンへのSSH接続を制限する設定例
初心者が最初に行う設定として多いのが、Linux(リナックス)サーバーへのSSH(エスエスエイチ)接続の許可です。22番ポートを使用しますが、これを全世界に公開(0.0.0.0/0)してしまうと、数分もしないうちに世界中から攻撃の試行が届きます。自分のパソコンのIPアドレスのみを許可する設定を、コマンドライン(Azure CLI)でのイメージで確認してみましょう。
az network nsg rule create --resource-group MyResourceGroup --nsg-name MyNSG --name AllowSSH --priority 100 --source-address-prefixes 203.0.113.5 --destination-port-ranges 22 --access Allow --protocol Tcp
{
"access": "Allow",
"name": "AllowSSH",
"priority": 100,
"protocol": "Tcp",
"sourceAddressPrefix": "203.0.113.5",
"destinationPortRange": "22"
}
上記のコマンドは、リソースグループ「MyResourceGroup」内にある「MyNSG」という名前のセキュリティグループに、自分のIP「203.0.113.5」から22番ポートへのアクセスを許可するルールを追加する例です。このように、特定のIPアドレスに絞り込むことがセキュリティの第一歩です。
5. Webサーバーの通信許可設定(HTTP/HTTPS)
次に、Webサーバーを公開する場合の設定を見てみましょう。Webサイトを公開するには、80番(HTTP)と443番(HTTPS)のポートを全開放する必要があります。ここでは、ルールのリストを管理するイメージをSQL(エスキューエル)のテーブル形式で表現してみます。データベースで管理されている設定値を参照するような感覚で見てください。
id | rule_name | priority | port | source | access
---+--------------+----------+------+-----------+-------
1 | AllowHTTP | 200 | 80 | Any | Allow
2 | AllowHTTPS | 210 | 443 | Any | Allow
3 | DenyAllIn | 65000 | Any | Any | Deny
この設定値を反映させるためのクエリを考えてみましょう。特定の条件に合致するルールを抽出する例です。
SELECT rule_name, access
FROM network_security_rules
WHERE destination_port IN (80, 443)
AND priority < 1000;
rule_name | access
-----------+-------
AllowHTTP | Allow
AllowHTTPS | Allow
このように、優先順位を考慮しながら、どのポートを開けるかを管理することが大切です。Webサーバーの場合は、不特定多数からのアクセスを許可しつつ、裏側のデータベースサーバーなどへの通信は制限をかけるといった多層防御が基本となります。
6. NSGの適用範囲:サブネットとネットワークインターフェース
NSGは、どこに適用するか(関連付けるか)によって効果が変わります。適用できる場所は主に2箇所あります。
- サブネット(Subnet): VNetを細かく区切ったグループ単位。そのサブネットに属するすべての仮想マシンに一括でルールが適用されます。管理が楽になるため、基本はこちらが推奨されます。
- ネットワークインターフェース(NIC): 個別の仮想マシンに付いているLANカードのようなもの。マシンごとに異なる細かい制限をかけたい場合に使います。
サブネットとNICの両方にNSGが適用されている場合、インバウンド通信では「サブネットのNSG」が先にチェックされ、次に「NICのNSG」がチェックされます。両方の関所をパスしないと通信が届かない仕組みです。アウトバウンド(出ていく通信)の場合は、逆に「NIC」が先で「サブネット」が後になります。この順序を間違えると、「設定したはずなのに通信できない!」というトラブルの元になります。
7. セキュリティ規則の優先順位をプログラム的に考える
NSGのルール評価ロジックは、プログラミングのif-else if文に非常に似ています。プログラムコードでその挙動をシミュレートしてみましょう。例えば、特定のポート番号を受け取って、通信を許可するか判定するロジックは以下のようになります。
int incomingPort = 80;
string sourceIp = "192.168.1.10";
if (sourceIp == "10.0.0.5" && incomingPort == 22)
{
Console.WriteLine("管理用IPからのSSH接続を許可します。");
}
else if (incomingPort == 80 || incomingPort == 443)
{
Console.WriteLine("Web通信(HTTP/HTTPS)を許可します。");
}
else
{
Console.WriteLine("既定のルール:それ以外の通信はすべて拒否(Deny)します。");
}
Web通信(HTTP/HTTPS)を許可します。
このコードからも分かる通り、最初に条件に一致した場所で処理が決まります。もし、一番上に「すべての通信を拒否」というルールを書いてしまうと、その下の許可ルールは一生実行されません。NSGの設定画面でも、この優先順位の数字(Priority)を意識して、上から順番に判定されることを忘れないようにしましょう。
8. アプリケーションセキュリティグループ(ASG)との併用
さらに高度な使い方として、ASG(Application Security Group)という機能があります。これはIPアドレスを直接指定するのではなく、「Webサーバーグループ」「DBサーバーグループ」といった名前(タグ)を付けて、そのグループ間での通信を制御する仕組みです。
IPアドレスはサーバーが増えたり減ったりするたびに変わる可能性がありますが、ASGを使えば「WebサーバーからDBサーバーへの通信を許可」という抽象的な書き方ができるため、設定のメンテナンスが劇的に楽になります。クラウドネイティブな環境では、IPアドレスに依存しない、こうした柔軟な設定がゼロトラストを支える技術となります。
9. NSG運用の注意点とトラブルシューティング
最後に、よくあるトラブルと解決策を紹介します。設定したはずなのに通信がつながらない場合、以下の項目をチェックしてみてください。
- 優先順位の競合: より優先度の高い(数字の小さい)ルールで拒否(Deny)されていないか確認する。
- 双方向の考慮: 戻りの通信は「ステートフル(Stateful)」という仕組みで自動的に許可されますが、新しいコネクションをどちらから張るかを再確認する。
- 既定のルールの確認: Azureには
AllowVNetInBound(VNet内通信は許可)などの標準ルールが存在します。これに意図せず合致していないか。 - 適用場所のミス: サブネットに適用したつもりが、別のサブネットだったというケアレスミス。
Azure portal(アジュール ポータル)には「ネットワーク監視」や「IPフロー検証」という診断ツールもあります。これらを使うと、どのルールが原因で通信が止まっているかを一発で特定できるので、初心者の方はぜひ活用してください。
まとめ
これまでに学んできたAzure NSG(ネットワークセキュリティグループ)の知識を整理しましょう。Azureにおけるネットワークセキュリティの要(かなめ)であるNSGは、単なるファイアウォール以上の役割を持っています。クラウド環境における「信頼しないことを前提とする」ゼロトラストモデルを具現化するための、最も基本的かつ強力なツールです。
NSGの本質は、インバウンド(受信)とアウトバウンド(送信)という二つの方向に対して、優先順位(Priority)に基づいたルール適用を行う点にあります。この優先順位の仕組みは、プログラミングにおける条件分岐のロジックと酷似しており、一度条件に合致すればその後のルールは評価されない「早い者勝ち」の原則が貫かれています。
また、運用面ではサブネット単位での適用が推奨される一方で、特定の仮想マシンに対してはネットワークインターフェース(NIC)単位での制御も可能です。これらを組み合わせることで、多層防御(Defense in Depth)を実現できます。さらに、IPアドレスに依存しないASG(アプリケーションセキュリティグループ)を活用することで、クラウドの柔軟性を損なうことなく、役割に基づいた直感的なセキュリティ管理が可能になります。
セキュリティ設定において最も重要なのは、「最小特権の原則」です。不要なポートはすべて閉じ、必要な通信だけを特定のソースからのみ許可する。この地道な積み重ねこそが、強固なインフラを構築する第一歩となります。
<h3>NSG設定のベストプラクティス:SQLによる構成管理のシミュレーション</h3> <p> 実際の現場では、多数のNSGルールを管理することになります。これをデータベースのテーブルのように構造化して理解しておくと、設定漏れを防ぐことができます。例えば、Webアプリケーション、データベース、管理用セグメントのルール構成を以下のように定義してみましょう。 </p> <p><strong>現在のNSGルール設定値(実行前)</strong></p>
id | rule_name | priority | port | source_ip | access | description
---+-------------------+----------+-------+-----------------+--------+----------------------
1 | Allow_Bastion_SSH | 100 | 22 | 10.0.1.4 | Allow | 踏み台サーバーからの接続
2 | Allow_Web_HTTPS | 200 | 443 | Any | Allow | 一般公開用HTTPS
3 | Allow_Web_HTTP | 210 | 80 | Any | Allow | 一般公開用HTTP
4 | Deny_All_Inbound | 4096 | Any | Any | Deny | 最終的な拒否ルール
特定の管理用IPアドレス(10.0.1.4)以外からの22番ポートへのアクセスが、正しく拒否されているか、あるいは意図しない「Allow」ルールが存在しないかを確認するためのSQLクエリを実行します。
SELECT rule_name, priority, access
FROM network_security_group_rules
WHERE destination_port = 22
AND source_ip != '10.0.1.4'
ORDER BY priority ASC;
rule_name | priority | access
-----------------+----------+-------
Deny_All_Inbound | 4096 | Deny
このように、優先順位が高い位置に「不特定多数からのSSH許可」が存在しないことを確認するのが運用の基本です。次に、新しく監視サーバー(10.0.2.10)からのICMP(Ping)通信を許可するルールを追加した後の状態を見てみましょう。
NSGルール設定値(ルール追加後)
id | rule_name | priority | port | source_ip | access | description
---+-------------------+----------+-------+-----------------+--------+----------------------
1 | Allow_Bastion_SSH | 100 | 22 | 10.0.1.4 | Allow | 踏み台サーバーからの接続
2 | Allow_Web_HTTPS | 200 | 443 | Any | Allow | 一般公開用HTTPS
3 | Allow_Web_HTTP | 210 | 80 | Any | Allow | 一般公開用HTTP
4 | Allow_Monitor_Ping| 300 | Any | 10.0.2.10 | Allow | 監視サーバーからの疎通確認
5 | Deny_All_Inbound | 4096 | Any | Any | Deny | 最終的な拒否ルール
C#による通信パケットのフィルタリング・シミュレーター
NSGの挙動をより深く理解するために、プログラムのオブジェクト指向的な観点からパケットフィルタリングをシミュレートしてみましょう。以下のコードは、受信したパケットの情報をクラスで定義し、NSGのルールリストと照らし合わせて「許可(Allow)」か「拒否(Deny)」かを判定するロジックです。
using System;
using System.Collections.Generic;
public class NetworkPacket
{
public string SourceIp { get; set; }
public int DestinationPort { get; set; }
public string Protocol { get; set; }
}
public class SecurityRule
{
public string Name { get; set; }
public int Priority { get; set; }
public int? Port { get; set; } // nullはAny(すべて)
public string SourceIp { get; set; }
public string Access { get; set; } // Allow or Deny
}
class Program
{
static void Main()
{
// ルールリストの定義(優先順位順)
var nsgRules = new List<SecurityRule>
{
new SecurityRule { Name = "SSH_Admin", Priority = 100, Port = 22, SourceIp = "203.0.113.5", Access = "Allow" },
new SecurityRule { Name = "Web_Traffic", Priority = 200, Port = 443, SourceIp = "Any", Access = "Allow" },
new SecurityRule { Name = "Default_Deny", Priority = 65000, Port = null, SourceIp = "Any", Access = "Deny" }
};
// テスト用のパケット(一般ユーザーからのHTTPS通信を想定)
var incomingPacket = new NetworkPacket { SourceIp = "1.2.3.4", DestinationPort = 443, Protocol = "TCP" };
string finalAction = "Deny"; // デフォルトは拒否
Console.WriteLine("--- パケット検修開始 ---");
foreach (var rule in nsgRules)
{
bool portMatch = rule.Port == null || rule.Port == incomingPacket.DestinationPort;
bool ipMatch = rule.SourceIp == "Any" || rule.SourceIp == incomingPacket.SourceIp;
if (portMatch && ipMatch)
{
finalAction = rule.Access;
Console.WriteLine($"合致したルール: {rule.Name} (優先度: {rule.Priority})");
Console.WriteLine($"判定結果: {rule.Access}");
break; // 最初にマッチしたルールで確定
}
}
Console.WriteLine("--- 最終的な通信処理: " + finalAction + " ---");
}
}
--- パケット検修開始 ---
合致したルール: Web_Traffic (優先度: 200)
判定結果: Allow
--- 最終的な通信処理: Allow ---
このシミュレーションでわかる通り、break文によってループを抜ける動作こそが、NSGの優先順位(Priority)の仕組みそのものです。もしWeb_Traffic(優先度200)よりも上に、すべての通信を拒否するルールを置いてしまうと、正規のWebアクセスも遮断されてしまうことになります。
トラブルを未然に防ぐ:Linuxコマンドによる診断
設定が完了したら、実際に通信が通るかどうかを確認する必要があります。Azureポータル上での確認はもちろんですが、仮想マシンの内部から「どのポートが開いているか」「外部に接続できるか」を確認するLinuxコマンドの知識も不可欠です。
指定したIPとポート(443)に対して通信が可能かチェック(ncコマンド)
nc -zv 203.0.113.10 443
Connection to 203.0.113.10 443 port [tcp/https] succeeded!
自身のサーバーで待ち受けているポートを確認
netstat -tuln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
NSGは「ネットワークの関所」ですが、サーバー内部のOSレベルでのファイアウォール(iptablesやufwなど)も存在します。NSGの設定が正しいのに通信できない場合は、OS側の設定や、サービスが正しく起動してポートを「LISTEN(待ち受け)」状態にしているかを確認することが重要です。
生徒
「先生、まとめを読んでNSGの仕組みがかなりクリアになりました!特に優先順位が『早い者勝ち』で、プログラムの条件分岐と同じだという説明がすごく分かりやすかったです。」
先生
「それは良かったです。優先順位(Priority)の数字は、後からルールを差し込めるように、100、200、300といった形で少し間隔を空けて設定するのがコツですよ。例えば100と101にしてしまうと、その間に新しいルールを入れたくなった時に困ってしまいますからね。」
生徒
「なるほど、設計の段階から余裕を持たせておくんですね。あと、ゼロトラストの話で『最小特権の原則』という言葉が出てきましたが、これは具体的にどう実践すればいいですか?」
先生
「良い質問ですね。例えば、SSH接続を許可する際に、ソース(送信元)を『Any(すべて)』にするのではなく、必ず自分のオフィスのIPアドレスや、VPN経由の特定のIPに絞ることです。また、サブネット単位でNSGを適用して、データベース層のサブネットにはWeb層からの通信しか許可しない、といった階層分けも効果的です。」
生徒
「サブネットとNICの両方にNSGを適用できるという話もありましたが、どっちで設定したか分からなくなりそうです。」
先生
「基本は『サブネット』で一括管理するのがおすすめですよ。個別のNICにバラバラに設定してしまうと、後で設定変更が必要になった時に、どのマシンに何を設定したか把握するのが大変になります。まずはサブネットで共通のルールを作り、どうしても必要な例外だけをNICで制御する、という二段構えがスマートです。」
生徒
「ステートフルな通信についても気になります。戻りの通信は自動で許可されるんですよね?」
先生
「その通りです!例えばインバウンドで80番ポートを許可すれば、それに対するサーバーからの返信(アウトバウンド)は、アウトバウンド規則で明示的に許可しなくても通ります。これを知っておくだけで、ルールの記述量が半分で済みますし、トラブルシューティングの際も混乱せずに済みますよ。」
生徒
「ありがとうございます!まずは自分の開発環境で、特定のIPアドレスだけを許可する最小構成のNSGを作ってみようと思います。Azureポータルの『IPフロー検証』も触ってみますね!」
先生
「その意気です!実際に手を動かして、わざと通信を拒否させてみて、思い通りにブロックされるかを確認するのも良い勉強になります。セキュリティは『正しく止める』ことができて初めて『正しく通す』ことができるようになりますから。頑張ってくださいね!」