AzureのNSGとSSH公開鍵認証でLinux VMを安全に保護する方法|ネットワークセキュリティグループの設定と実践例

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Azure, セキュリティ > AzureのNSGとSSH公開鍵認証でLinux VMを安全に保護する方法|ネットワークセキュリティグループの設定と実践例
「Azureで作ったLinux VMがどこからでもSSHで叩けてしまう。セキュリティ設定、何から手をつければいいんだろう」
クラウドにサーバーを立てた直後にこういった不安を感じるのは、現場エンジニアなら誰しも経験することです。パブリッククラウドの検証サーバーは、オンプレと違ってインターネットから直接アクセスできる状態で起動します。ファイアウォール相当の設定を後回しにすると、SSH辞書攻撃のログが大量に積み上がります。

この記事では、AzureのLinux VMに対してSSH公開鍵認証を設定し、NSG(ネットワークセキュリティグループ)で接続元IPを絞り込む実践的な手順を解説します。Azure CLIとAzureポータル両面から操作し、設定後の動作確認まで一通り追えるよう構成しました。

この記事のポイント

・Azure NSGの受信セキュリティ規則でSSHを特定IPに限定できる
・SSH公開鍵認証をAzure CLIで後から追加する手順を実機で確認
・パスワード認証を無効化してブルートフォース攻撃を根本から防ぐ
・NSG規則の優先度(Priority)で複数IP許可・全IP拒否を組み合わせる


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

AzureのNSGとは何か|Linuxのfirewalldとどこがちがうのか

NSG(Network Security Group)はAzureが提供するL4レベルのフィルタリング機能で、送信元IP・プロトコル・ポートの組み合わせで通信の許可/拒否を制御します。

オンプレミスでいうと「サーバーの外側に置かれたルーターのACL」に近いイメージです。Linuxのfirewalldiptablesはサーバー内部で動くのに対し、NSGはAzureのネットワーク基盤側で動きます。つまりNSGで拒否されたパケットはVM自体には届かず、journalctlにも残りません。

NSGには2つのアタッチポイントがあります。

NIC(ネットワークインターフェイス)に紐付け:そのVMだけに適用される
サブネットに紐付け:同じサブネット内の全VMに一括適用される

本記事では「NICに紐付けたNSGで特定VMを個別制御する方法」を扱います。

規則は優先度(Priority)の数値が小さいほど先に評価されます。100~4096の範囲で指定でき、同じ優先度は設定できません。「許可する規則を低い番号に、拒否する規則を高い番号に」と覚えてください。

なぜSSH公開鍵認証が必須なのか|パスワード認証の危険性を数字で見る

Azure上でパスワード認証を有効にしたまま22番ポートを全IPに開けておくと、数十分で辞書攻撃が始まります。実際の検証サーバーのSSH認証ログを見ると:

# journalctl -u sshd --since "1 hour ago" | grep "Failed password" | wc -l 2347 # journalctl -u sshd --since "1 hour ago" | grep "Failed password" | awk '{print $11}' | sort | uniq -c | sort -rn | head -5 312 198.xx.xx.xx 287 45.yy.yy.yy 201 103.zz.zz.zz 89 185.aa.aa.aa 67 91.bb.bb.bb

1時間で2,347件の失敗ログが積み上がっていました。公開から6時間後の実測値です。

公開鍵認証に切り替えると、鍵ファイルを持たない接続は一切認証に進めないため、辞書攻撃は根本的に無効化されます。NSGで接続元IPを絞ることで、鍵が漏洩した場合の被害も最小化できます。

SSH公開鍵認証の設定手順|Azure CLIを使う方法

1. ローカルマシンでSSH鍵ペアを生成する

まずローカルの作業PCでED25519鍵ペアを生成します。RSA 2048bitより短く、セキュリティ強度は高い現在の推奨方式です。

# 実行環境: ローカルPC(Windows WSL2 / macOS / Linux) ssh-keygen -t ed25519 -C "azure-linuxvm-key" -f ~/.ssh/azure_vm_key # 出力例 Generating public/private ed25519 key pair. Enter passphrase (empty for no passphrase): (パスフレーズを入力。空はNG) Enter same passphrase again: Your identification has been saved in /home/user/.ssh/azure_vm_key Your public key has been saved in /home/user/.ssh/azure_vm_key.pub The key fingerprint is: SHA256:xXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX azure-linuxvm-key

生成されたファイルのうち、azure_vm_key(秘密鍵)はローカルから絶対に持ち出さないこと。 Azureに登録するのはazure_vm_key.pub(公開鍵)だけです。

2. 既存VMに公開鍵を追加する(Azure CLI)

VMがすでに稼働している場合、az vm user updateコマンドで公開鍵を追加します。

# 実行環境: Azure Cloud Shell または az CLI が使えるローカル環境 # RHEL 9.4 / Ubuntu 24.04 LTS の Azure VMで動作確認済み # 変数を設定 RG="myResourceGroup" VM_NAME="myLinuxVM" USERNAME="azureuser" PUBKEY_PATH="~/.ssh/azure_vm_key.pub" # 公開鍵を既存VMに追加 az vm user update \ --resource-group "$RG" \ --name "$VM_NAME" \ --username "$USERNAME" \ --ssh-key-value "$(cat $PUBKEY_PATH)" # 出力例(成功時) { "homeDirectory": "", "password": null, "sshAuthorizedKeys": [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB... azure-linuxvm-key" ], "username": "azureuser" }

3. VM側でパスワード認証を無効化する

公開鍵を追加した後、VM内でSSHデーモンの設定を変更してパスワード認証を無効にします。

# 公開鍵認証でVMにログイン(変更前に必ず成功を確認すること) ssh -i ~/.ssh/azure_vm_key azureuser@xx.xx.xx.xx # 以下はVM内での作業 # PasswordAuthentication を no に変更 sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config # 設定確認 grep "PasswordAuthentication" /etc/ssh/sshd_config # 出力例 PasswordAuthentication no # SSHデーモンを再起動 sudo systemctl restart sshd # 再起動後もサービスが正常か確認 sudo systemctl status sshd | grep "Active:" # 出力例 Active: active (running) since Sat 2026-06-27 10:15:33 UTC; 3s ago

重要: sshd再起動前に、公開鍵認証でのログインが成功することを別のターミナルで確認してください。ログインできないままパスワード認証を無効にするとVMにアクセスできなくなります。

NSGで接続元IPを絞り込む手順|Azure CLI実践

1. 現在のNSGと規則を確認する

# VMに紐付いたNSG名を確認 az network nic show \ --resource-group "$RG" \ --name "${VM_NAME}VMNic" \ --query "networkSecurityGroup.id" \ --output tsv # 出力例 /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkSecurityGroups/myLinuxVMNSG NSG_NAME="myLinuxVMNSG" # 現在の受信セキュリティ規則を一覧表示 az network nsg rule list \ --resource-group "$RG" \ --nsg-name "$NSG_NAME" \ --output table # 出力例(デフォルト状態) Name ResourceGroup Priority SourceAddressPrefixes SourcePortRanges DestinationAddressPrefixes DestinationPortRanges Protocol Access Direction ----------------------- --------------- ---------- ----------------------- ------------------ ---------------------------- ----------------------- ---------- -------- ----------- SSH myResourceGroup 1000 * * * 22 TCP Allow Inbound

デフォルトでは*(全IP)からSSHを許可しています。これを自分のIPに限定します。

2. 接続元IPを許可する規則を追加する

# 自分のグローバルIPアドレスを確認(ローカルPCから実行) curl -s https://ifconfig.me # 出力例 203.0.113.45 MY_IP="203.0.113.45" # 許可規則を追加(優先度100 = 最優先で評価) az network nsg rule create \ --resource-group "$RG" \ --nsg-name "$NSG_NAME" \ --name "Allow-SSH-MyIP" \ --priority 100 \ --protocol Tcp \ --direction Inbound \ --source-address-prefixes "$MY_IP" \ --source-port-ranges "*" \ --destination-address-prefixes "*" \ --destination-port-ranges 22 \ --access Allow # 出力例(成功時) { "access": "Allow", "destinationPortRange": "22", "name": "Allow-SSH-MyIP", "priority": 100, "protocol": "Tcp", "sourceAddressPrefix": "203.0.113.45", ... }

3. 全IPからのSSHを拒否する規則を追加する

# 全IPからのSSHを拒否(優先度200 = Allow-SSH-MyIPの後に評価) az network nsg rule create \ --resource-group "$RG" \ --nsg-name "$NSG_NAME" \ --name "Deny-SSH-All" \ --priority 200 \ --protocol Tcp \ --direction Inbound \ --source-address-prefixes "*" \ --source-port-ranges "*" \ --destination-address-prefixes "*" \ --destination-port-ranges 22 \ --access Deny # 設定後の規則を確認 az network nsg rule list \ --resource-group "$RG" \ --nsg-name "$NSG_NAME" \ --output table # 出力例(設定後) Name Priority SourceAddressPrefixes DestinationPortRanges Access ----------------------- ---------- ----------------------- ----------------------- -------- Allow-SSH-MyIP 100 203.0.113.45 22 Allow Deny-SSH-All 200 * 22 Deny SSH 1000 * 22 Allow

優先度100のAllow-SSH-MyIPが先に評価されるため、203.0.113.45からのSSHは許可されます。それ以外のIPは優先度200のDeny-SSH-Allで拒否されます(優先度1000の既存SSH規則には到達しません)。

4. 動作確認|許可・拒否の両方をテストする

# 許可されたIPからのSSH接続確認(成功するはず) ssh -i ~/.ssh/azure_vm_key -o ConnectTimeout=10 azureuser@xx.xx.xx.xx # 出力例 Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-1021-azure x86_64) Last login: Sat Jun 27 10:15:33 2026 from 203.0.113.45 # 別のIPからの接続を試みる場合(Azure Cloud Shellからテスト) # Cloud Shellは異なるIPのため拒否される ssh -o ConnectTimeout=10 azureuser@xx.xx.xx.xx # 出力例(NSGに拒否された場合) ssh: connect to host xx.xx.xx.xx port 22: Connection timed out

拒否された場合は「Connection refused」ではなく「Connection timed out」になります。これがNSGのデフォルト動作で、パケットを無視(DROP)する形で拒否します。

複数拠点から接続したい場合の応用Tips

オフィスと自宅の両方からアクセスしたい場合、--source-address-prefixesにCIDR形式で複数のIPまたは範囲を指定します。

# 複数のIPアドレスを1つの規則で許可(スペース区切り) az network nsg rule update \ --resource-group "$RG" \ --nsg-name "$NSG_NAME" \ --name "Allow-SSH-MyIP" \ --source-address-prefixes "203.0.113.45" "198.51.100.20" # サブネット全体を許可する場合(例: 社内ネットワーク 10.0.0.0/24) az network nsg rule update \ --resource-group "$RG" \ --nsg-name "$NSG_NAME" \ --name "Allow-SSH-MyIP" \ --source-address-prefixes "203.0.113.45" "10.0.0.0/24"

また、AzureのJIT(Just-In-Time)VMアクセスを使うと、必要な時だけ自分のIPへのSSHを一時的に開放し、時間が経過すると自動的に閉じる仕組みも利用できます(Microsoft Defender for Cloud が必要)。

JITアクセスの利点:SSHポートを常時開放しなくて済む
JITアクセスの欠点:Microsoft Defender for Cloud(旧 Azure Security Center)の有効化が必要でコストが増える

本番環境ではJITの導入を検討し、開発・検証サーバーはNSGによるIP制限で運用するのが現実的なバランスです。

NSG設定のよくあるトラブルと対処法

「Connection timed out」になって自分のIPからも繋がらない

考えられる原因は2つです。

グローバルIPが変わっている:プロバイダによっては動的IPのため、再度curl -s https://ifconfig.meで確認してNSG規則を更新する
サブネットにも別のNSGが紐付いている:NIC単体のNSGは許可していても、サブネット側NSGが拒否しているケース。az network vnet subnet showでサブネットのNSGも確認する

# サブネットに紐付いたNSGを確認 az network vnet subnet show \ --resource-group "$RG" \ --vnet-name "myVNet" \ --name "mySubnet" \ --query "networkSecurityGroup.id" \ --output tsv # 出力例(NSGなし) None # 出力例(NSGあり) /subscriptions/xxx.../networkSecurityGroups/mySubnetNSG

NSGは更新したのに反映されない

NSG規則の変更は通常数秒以内に反映されますが、キャッシュの影響で最大1分ほどかかることがあります。az network nsg rule showで規則が正しく更新されていることを確認してから、再度SSH接続を試みてください。

PasswordAuthentication no にしたらVMに入れなくなった

AzureにはVM拡張機能(VMAccess)を使ってSSH公開鍵をリセットする仕組みがあります。

# VMAccessを使ってSSH公開鍵をリセット(ロックアウト時の復旧手順) az vm user reset-ssh \ --resource-group "$RG" \ --name "$VM_NAME" # または新しい公開鍵を強制上書き az vm user update \ --resource-group "$RG" \ --name "$VM_NAME" \ --username "$USERNAME" \ --ssh-key-value "$(cat ~/.ssh/new_key.pub)"

パスワード認証を無効にする前に、必ず公開鍵でのログインを成功させてから設定変更するのが鉄則です。

本記事のまとめ

Azure Linux VMのセキュリティ設定について、NSGとSSH公開鍵認証の2段構えで保護する手順を解説しました。
やること コマンド・設定
ED25519鍵ペアを生成する ssh-keygen -t ed25519 -f ~/.ssh/azure_vm_key
既存VMに公開鍵を追加する az vm user update --ssh-key-value "$(cat key.pub)"
パスワード認証を無効化する PasswordAuthentication no + systemctl restart sshd
自分のIPからのSSHを許可する az network nsg rule create --access Allow --priority 100
全IPからのSSHを拒否する az network nsg rule create --access Deny --priority 200
サブネットのNSGを確認する az network vnet subnet show --query "networkSecurityGroup.id"
ロックアウト時に公開鍵をリセットする az vm user reset-ssh または az vm user update
NSGで接続元IPを絞る+SSH公開鍵認証の組み合わせが、Azure Linux VMのセキュリティ基本セットです。Postfix TLS設定の手順と組み合わせることで、メール配送経路のセキュリティも同時に強化できます。また、Linux DNS設定の基本も押さえておくと、AzureのプライベートDNSゾーンを活用した名前解決設計につながります。

Azure上でLinuxを安全に扱う技術はクラウドエンジニアの必須スキルです。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、AzureでのLinux VM運用を体系的に学びたいなら、Azure実践ハンズオン講座をご覧ください。NSG・SSH鍵認証から始まるセキュリティ設計を、現役エンジニアの実務視点で一気に習得できます。

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

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

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

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

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

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

登録10秒/合わなければ解除3秒 / 詳細はこちら

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

この記事を書いた人

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

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

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