クラウドにサーバーを立てた直後にこういった不安を感じるのは、現場エンジニアなら誰しも経験することです。パブリッククラウドの検証サーバーは、オンプレと違ってインターネットから直接アクセスできる状態で起動します。ファイアウォール相当の設定を後回しにすると、SSH辞書攻撃のログが大量に積み上がります。
この記事では、AzureのLinux VMに対してSSH公開鍵認証を設定し、NSG(ネットワークセキュリティグループ)で接続元IPを絞り込む実践的な手順を解説します。Azure CLIとAzureポータル両面から操作し、設定後の動作確認まで一通り追えるよう構成しました。
この記事のポイント
・Azure NSGの受信セキュリティ規則でSSHを特定IPに限定できる
・SSH公開鍵認証をAzure CLIで後から追加する手順を実機で確認
・パスワード認証を無効化してブルートフォース攻撃を根本から防ぐ
・NSG規則の優先度(Priority)で複数IP許可・全IP拒否を組み合わせる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
AzureのNSGとは何か|Linuxのfirewalldとどこがちがうのか
NSG(Network Security Group)はAzureが提供するL4レベルのフィルタリング機能で、送信元IP・プロトコル・ポートの組み合わせで通信の許可/拒否を制御します。オンプレミスでいうと「サーバーの外側に置かれたルーターのACL」に近いイメージです。Linuxの
firewalldやiptablesはサーバー内部で動くのに対し、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
公開鍵認証に切り替えると、鍵ファイルを持たない接続は一切認証に進めないため、辞書攻撃は根本的に無効化されます。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
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
複数拠点から接続したい場合の応用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"
・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 |
Azure上でLinuxを安全に扱う技術はクラウドエンジニアの必須スキルです。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、AzureでのLinux VM運用を体系的に学びたいなら、Azure実践ハンズオン講座をご覧ください。NSG・SSH鍵認証から始まるセキュリティ設計を、現役エンジニアの実務視点で一気に習得できます。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 前のページへ:AzureのVMSSとLoad Balancerで高可用性を実現する方法|スケールセット構築と自動スケーリングの実践ハンズオン
- この記事の属するカテゴリ:Azure・セキュリティへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます