Azure VMのAutopilotリセット後にRDP接続できない原因と対処 ― Bastion/Serial Consoleでの監視と、ラボ検証のベストプラクティス
Windows Autopilotの検証のためにAzure仮想マシン(Azure VM)を「リセット」したところ、ポータルでは「実行中(利用可能)」と表示されるにもかかわらずRDP(3389/TCP)で接続できない――この状況は、AutopilotやIntuneのラボ検証で多くの管理者が遭遇します。さらに、Azure Bastion経由でも「到達不可」となり、Serial Consoleが無反応、Boot DiagnosticsにはWindowsのログイン(またはOOBE)画面が映っている、といった“見えているのに触れない”状態に陥りがちです。
本記事では、なぜRDPが使えなくなるのかという根本原因から、Autopilot進行中のリモート監視・操作方法、テストの生産性を上げるための設計・運用ノウハウまで、実運用で役立つ手順とチェックリストを包括的に解説します。外部リンクなしでそのままWordPressに貼り付け可能な形式でまとめました。
症状の整理(よくある問い合わせ状況)
- Autopilotの「リセット」実行後、AzureポータルのVM状態は「実行中(利用可能)」。
- NSGで3389/TCPを許可していても、RDP接続が失敗する。
- Azure Bastion経由でも「到達不可」となることがある。
- Serial Consoleが無反応のように見える。
- Boot DiagnosticsにはWindowsのログインまたはOOBE画面が表示されている。
結論(先に要点)
- OOBE(初期設定)中はRDPサービスが起動しない/使えない構成になっていることが多い。AutopilotのESP(Enrollment Status Page)完了までRDPは使えない前提で設計する。
- 監視・操作はAzure BastionまたはSerial Consoleを活用する。ただしBastionは内部的にRDP/3389を利用するため、TermServiceが停止・無効の段階ではBastionでも接続できない。この場合はSerial ConsoleやRun command(Azure VMエージェント経由)で対処する。
- Autopilot事前プロビジョニング(旧称:White Glove)を使えば、ユーザー引き渡し前にESP・アプリ配布を完了でき、RDP不通の空白期間による詰まりを回避可能。
- 進捗の可視化はIntune管理センターのWindows Enrollment > Deployment Status(Device Setup / Account Setup)で行う。
- ラボ検証を繰り返すなら、Sysprep済みゴールデンイメージ+Compute Galleryのバージョン管理+Bastion/Serial Consoleの下準備をテンプレ化する。
なぜRDPできないのか ― OOBE/ESPの仕組みとRDPサービスの関係
「リセット」直後のOSは一般にOOBE(Out-Of-Box Experience)フェーズに戻ります。Autopilotのプロファイル適用やESPの進行、デバイス登録・MDM登録・ポリシー配布・アプリ導入などが段階的に走ります。この期間は次のいずれかの理由で外部RDPが成立しません。
- TermService(Remote Desktop Services)が未起動/無効、またはファイアウォールでRDPが未開放。
- NLA(Network Level Authentication)やアカウント準備が未完了で、ログオン前RDPを拒否。
- ESPの順序やポリシー適用により、RDP有効化の設定が後段に回っている。
フェーズごとの典型状態を以下にまとめます(環境・イメージにより差異あり)。
| フェーズ | TermService | Windows Defender Firewall(RDPルール) | RDP可否 | 備考 |
|---|---|---|---|---|
| OOBE開始直後 | 未起動/無効のことが多い | 未開放のことが多い | 不可 | Boot Diagnosticsには画面が映っても操作不可 |
| ESP(Device Setup)途中 | 自動起動未設定のケースあり | ポリシー未適用の可能性 | 不可〜不安定 | Intuneで進捗確認推奨 |
| ESP完了後 | 起動/自動起動が整う | RDP許可ルールが有効化 | 可 | RDPで安定接続 |
Autopilot進行中の監視・操作手段
1) Azure Bastion
Azure BastionはVMのプライベートIPに対して安全にRDP/SSH接続を提供します。VM側のRDPサービスが動作していることが前提なので、OOBE直後の段階では接続不可の可能性が高い点に注意してください。Bastion経由での接続が前提なら、RDP有効化を“前倒し”にする仕込み(後述)を必ず行います。
接続の基本要件:
- 同一VNet内にAzureBastionSubnet(/27以上)を持つBastionホストが配置されている。
- VMのNIC/サブネット/NSGで、3389/TCPの受信が少なくともBastionホストから許可されている(推奨:送信元「AzureBastion」サービス タグまたは同一VNet)。
- ユーザー側ブラウザのポップアップブロック無効化。
注意:管理プレーン用IP 168.63.129.16 はプラットフォーム通信(DHCP/DNSプローブ等)で使われます。BastionのRDP経路そのものはこのIPから来ません。VMのNSGでRDP許可を行う際は、「AzureBastion」サービス タグやBastionホストのプライベートIPレンジを想定してください。
「到達不可」時のチェックリスト
- BastionホストとVMが同一リージョン・同一VNet(対ピアリング含む)で通信できるか。
- AzureBastionSubnetが/27以上で確保されているか。
- NSG/UdRでRDP 3389の受信/必要な東西通信を阻害していないか。
- Bastionホスト側のNSGでアウトバウンド443/TCP等を塞いでいないか。
- VM側でTermService・Firewall設定が有効か(後述のRun commandで確認・修復可能)。
2) Serial Console(Windows SAC)
AzureのSerial Consoleは、OSのネットワークが不調でもテキストベースでコンソールに入れる強力な手段です。BastionがRDP不可のタイミングでも、SACが生きていればローカル管理者資格情報でログオンし、サービス・レジストリ・イベントログを直接確認できます。
前提条件:
- ブート診断(Boot Diagnostics)が有効(標準的なAzureイメージは既定で有効)。
- WindowsのEMS/SACが有効(標準イメージは有効なことが多い。カスタムイメージは事前確認必須)。
もしSACが無効化されている疑いがあれば、通常起動可能なタイミングで以下を仕込んでおくと安全です(管理者PowerShell):
# EMS/SACを明示有効化(再起動が必要)
bcdedit /ems {current} on
bcdedit /emssettings EMSPORT:COM1 EMSBAUDRATE:115200
Serial Consoleに入れたら、以下のように状況を確認します。
# コマンドプロンプト起動(SACチャンネルから)
cmd
# RDPの有効化(RDPサービスとFW)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
sc.exe config TermService start= auto
sc.exe start TermService
# 最小限のFW許可ルール(重複作成OK)
netsh advfirewall firewall add rule name="RDP-In-TCP-3389" dir=in action=allow protocol=TCP localport=3389
# Autopilot/MDM関連ログの直近確認例
powershell -NoProfile -Command ^
"Get-WinEvent -LogName 'Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin' -MaxEvents 50 |" ^
"ft TimeCreated,Id,LevelDisplayName,Message -AutoSize"
powershell -NoProfile -Command ^
"Get-WinEvent -LogName 'Microsoft-Windows-ModernDeployment-Diagnostics-Provider/Autopilot' -MaxEvents 100 |" ^
"ft TimeCreated,Id,LevelDisplayName,Message -AutoSize"
「RDPを失わずにAutopilotを進める」ための実践手順
カギはOOBE直後~ESP途中のタイミングで、RDPサービスとFWを先に整える仕込みです。AzureにはRun commandや拡張機能(Custom Script Extension)といった“ゲストエージェント経由の注入手段”があるため、ネットワークRDPが不通でも復旧できる余地があります。
方法A:Azure「Run command」でRDPを有効化
- Azureポータル > VM > Run command(Windows)を開く。
- 「スクリプトの実行」を選択し、次のようなコマンドを投入する。
# RDPとFWを前倒しで有効化(管理者PowerShellとして実行)
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 0
Start-Process sc.exe -ArgumentList 'config TermService start= auto' -NoNewWindow -Wait
Start-Process sc.exe -ArgumentList 'start TermService' -NoNewWindow -Wait
# 重複しても安全な明示ルール
if (-not (Get-NetFirewallRule -Name 'RDP-In-TCP-3389' -ErrorAction SilentlyContinue)) {
New-NetFirewallRule -Name 'RDP-In-TCP-3389' -DisplayName 'RDP-In-TCP-3389' -Direction Inbound -Protocol TCP -LocalPort 3389 -Action Allow
} else {
Enable-NetFirewallRule -Name 'RDP-In-TCP-3389'
}
注:DisplayGroup名に依存しない明示ルール作成方式にしておくと、OSの言語やローカライズ差異に強くなります。
方法B:Custom Script Extensionで“常にRDP前倒し”をテンプレ化
ラボ検証を繰り返すなら、VMデプロイ直後にRDPを有効化するスクリプトを拡張機能で流す設計が便利です。ARM/Bicep/terraform/CLIいずれでも定義できます。例(PowerShellスクリプト本体):
# enable-rdp.ps1
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 0
Start-Process sc.exe -ArgumentList 'config TermService start= auto' -NoNewWindow -Wait
Start-Process sc.exe -ArgumentList 'start TermService' -NoNewWindow -Wait
if (-not (Get-NetFirewallRule -Name 'RDP-In-TCP-3389' -ErrorAction SilentlyContinue)) {
New-NetFirewallRule -Name 'RDP-In-TCP-3389' -DisplayName 'RDP-In-TCP-3389' -Direction Inbound -Protocol TCP -LocalPort 3389 -Action Allow
} else {
Enable-NetFirewallRule -Name 'RDP-In-TCP-3389'
}
これをストレージに置くか、インラインで拡張機能に流しておけば、「リセット」直後でも早い段階でRDPが戻るようになります。
方法C:Autopilot ESPの“前段でRDP有効化”ポリシーを適用
Intuneのデバイス構成・エンドポイントセキュリティで、RDP関連のFirewall規則やサービス自動起動をDevice Setupフェーズの早い段階に適用するよう設計します。ただし、ESPの評価順序や依存関係で前倒しにならないケースもありうるため、確実性を増すにはA/Bの併用が有効です。
Autopilotの進捗をリモートで確認する(Intune管理センター)
RDPが不通でも、Intune管理センター > デバイス > Windows Enrollment > Deployment Statusで以下を確認できます。
- Device Setup(デバイス構成・証明書・Win32アプリなど)
- Account Setup(ユーザー構成・アプリ・スクリプトなど)
失敗が出ている場合は、対象ポリシー・アプリの詳細を開き、依存関係・タイムアウト・配布リング・デリバリ最適化の帯域設定などを見直します。WinGet/Win32アプリの大型配布が詰まっていると、OOBEの滞留=RDP復帰の遅延に直結します。
Boot Diagnosticsで画面が見えるのに操作できない理由
Boot Diagnosticsは“スクリーンショット”としてOSの画面をキャプチャする機能で、対話操作はできません。OOBE画面が映っていても、RDPやBastionが不通なら進める術はなく、Serial ConsoleかRun commandを使って裏側からサービスやログを触る、というのがAzure流の運用になります。
Bastionが接続できないときの追加チェックポイント(まとめ)
| 観点 | 確認事項 | 対処 |
|---|---|---|
| VNet/リージョン | BastionホストとVMが同一リージョン・同一VNetか | 同一VNet配置(または適切なピアリング)に統一 |
| サブネット | AzureBastionSubnetが/27以上か | サブネットサイズを拡大(/27以上) |
| NSG(VM側) | 3389/TCPの受信を許可しているか | 送信元にAzureBastionサービス タグまたはVNetを設定 |
| NSG(Bastion側) | アウトバウンド443/TCPが許可されているか | 既定許可または明示許可に戻す |
| TermService | サービス起動・自動起動設定 | Run commandでRDP前倒し有効化 |
| Firewall | RDPルールの有効化 | 明示ルールを作成(3389/TCP) |
Serial Consoleでの深掘り診断(イベントログとAutopilotログ)
OOBE/ESPの停滞を見極めるには、イベントログが強力です。以下はSACからの例です。
# MDM/Autopilot系イベント
powershell -NoProfile -Command ^
"Get-WinEvent -LogName 'Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin' -MaxEvents 200 |" ^
"Sort-Object TimeCreated | Select-Object TimeCreated,Id,LevelDisplayName,Message | Format-List"
powershell -NoProfile -Command ^
"Get-WinEvent -LogName 'Microsoft-Windows-ModernDeployment-Diagnostics-Provider/Autopilot' -MaxEvents 200 |" ^
"Sort-Object TimeCreated | Select-Object TimeCreated,Id,LevelDisplayName,Message | Format-List"
# Azure AD Join / PRTの状態
dsregcmd /status
# Windows Updateの進捗(大規模パッチが足を引っ張ることがある)
powershell -NoProfile -Command ^
"Get-WinEvent -LogName 'Microsoft-Windows-WindowsUpdateClient/Operational' -MaxEvents 100 | ft TimeCreated,Id,Message -AutoSize"
ログディレクトリ(例):
C:\Windows\Provisioning\Autopilot\C:\Windows\Logs\Autopilot\C:\Windows\Temp\MDMDiagnostics\
ラボ検証を高速に回すためのベストプラクティス
1) ゴールデンイメージ+Compute Galleryで“使い捨て”を量産
- Sysprep(/generalize /oobe /shutdown)した汎用イメージをキャプチャ。
- Azure Compute Galleryでバージョン管理し、必要数を並行デプロイ。
- OS更新やアプリ更新をイメージに取り込み、AutopilotのOOBE時間を短縮。
# 例:Sysprep(VM内で実行)
%WINDIR%\System32\Sysprep\Sysprep.exe /generalize /oobe /shutdown
# 例:RDP前倒しをイメージ側に仕込む(起動スクリプト/タスクスケジューラ)
# 初回ブート時にRDP有効化を走らせる設計
2) ネットワークは「固定の箱」を再利用
- サブネット/NSG/ルートテーブル/Bastionを固定リソースとして用意。
- VMはプライベートIPとNIC名の命名規則を整え、DNS名(Private DNS Zone)も活用。
- NSGはテンプレ化(3389はVNet(またはAzureBastion)からのみ許可)。
3) OOBE完了までBastion/Serial Consoleを主役に
- RDPは「ESP完了後に戻る」という前提で、最初からBastion/Serial Consoleで操作。Serial Consoleの資格情報・EMS有効化は必ず事前に検証。
- Run commandでの復旧スクリプトを用意しておき、ワンクリックでRDP復帰できるようにする。
4) Autopilot事前プロビジョニング(pre-provisioning)を基本に
- ITがESPと主要アプリの導入をあらかじめ完了し、ユーザー受領時の待ち時間とトラブルを削減。
- 大型アプリやドライバー更新は事前フェーズに寄せ、OOBE中のネットワーク負荷を下げる。
5) Windows Updateの“重さ”を制御
- 配布リング/期限の設計で、OOBE同時多発の大型更新を抑制。
- 検証用には必要最小限のアップデートに留め、本番想定のテストは別途段階的に。
よくある落とし穴と回避策
- 「Bastionがあるのに繋がらない」:RDPサービスが未起動の段階。Serial ConsoleかRun commandでRDPを起こす。
- 「NSGは開けたのにダメ」:FirewallとTermServiceの同時対処が必須。どちらか片方だけでは失敗する。
- 「Boot Diagnosticsで画面が見える」:あくまで静止画。操作できない点を理解する。
- 「Serial Consoleに入れない」:EMS/SACの無効化や資格情報不備が原因。イメージ側でEMSを有効化しておく。
- 「Reset後に想定外のポリシーが効く」:割り当てスコープ・フィルターの見直し。検証用グループで最小限の構成から始める。
復旧フロー(迷ったらこの順で)
- Boot DiagnosticsでOSが起動していそうか(ブルースクリーンや停止ではないか)を目視。
- Serial Consoleに入り、TermService・Firewallを前倒し有効化(前掲コマンド)。
- Serial Consoleが不可なら、Run commandでRDP前倒しスクリプトを実行。
- 再びBastion経由RDPをテスト。接続できたら、イベントログでAutopilot/ESPの停滞箇所を特定。
- 以後の検証向けにCustom Script Extensionまたは起動スクリプトをテンプレ化して焼き込み。
NSG/Firewallの設計例(最小権限で安全に)
| 対象 | 方向 | プロトコル/ポート | 送信元/宛先 | 備考 |
|---|---|---|---|---|
| VM NSG | 受信 | TCP/3389 | AzureBastion(またはVNet)→ VM | インターネットからは閉塞。Bastion経由に限定 |
| VM Firewall | 受信 | TCP/3389 | 任意 | NSGで到達元を絞る前提。ルールは明示作成が安全 |
| Bastion NSG | 送信 | TCP/443ほか既定 | 外向きプラットフォーム通信 | 誤って遮断しない |
まとめ:安全に“空白期間”を乗り切る設計思想
- RDPはOOBE/ESPが終わるまで使えない――この前提を受け入れる。
- そのうえで、Serial ConsoleとRun commandを使ってRDP有効化を前倒しできる“裏口”を確保する。
- Autopilot事前プロビジョニングにより、ユーザー渡し前に大半の重い処理を完了させる。
- ラボではゴールデンイメージ+Compute Gallery+Bastion/Serial Console準備で、失敗しても即やり直せる体制を整える。
これらを実践すれば、Autopilotプロビジョニング中でもVMの状態を正しく把握・制御でき、RDPが有効になるまでの“触れない時間”を安全に短縮できます。
付録:チェックリスト(コピペ用)
[設計]
- 事前にBastion/Serial Consoleを用意(AzureBastionSubnet /27以上、EMS有効)。
- NSGは3389/TCPをBastion(またはVNet)からのみ許可。インターネットは閉塞。
- 起動スクリプト/拡張機能でRDPとFWを前倒し有効化。
- IntuneのESP順序:RDP関連(FW/サービス)はできるだけ前段に。
- 事前プロビジョニングで大型アプリ・更新を消化。
[復旧]
- Boot Diagnosticsで起動状態を確認。
- Serial ConsoleでTermService起動・FW許可・ログ採取。
- Serial Console不可ならRun commandで復旧スクリプト。
- Bastion経由RDPを再テスト。
- IntuneのDeployment Statusで失敗コンテンツを特定。
[ラボ運用]
- Sysprep汎用化→Compute Galleryでバージョン管理。
- ネットワーク(VNet/NSG/RT)は固定の箱を再利用。
- Run commandテンプレ、Custom Script Extensionを標準化。
よくあるQ&A
- Q: ポータルは「実行中」なのに、なぜRDPできない?
A: OSは動作していますが、OOBE/ESP中はRDPサービスやFWが未整備のため接続を拒否します。 - Q: Bastionなら必ず繋がる?
A: いいえ。Bastionも内部的にはRDP/3389を使うため、TermServiceが止まっていれば不可です。Serial ConsoleやRun commandで復旧します。 - Q: 168.63.129.16をNSGで許可すればBastionは通る?
A: これは管理プレーン通信のための特殊IPで、BastionのRDP到達元ではありません。RDPのNSGはAzureBastionサービス タグまたはVNetからの許可で設計します。 - Q: Serial Consoleで何ができる?
A: ローカル管理者でログオンし、サービス起動・レジストリ編集・ログ採取・診断が可能です。
最後に、本記事のエッセンスをもう一度:
- Autopilotリセット直後はRDPが使えないのが正常。
- Bastion/Serial Console/Run commandで“外から触れる手”を用意する。
- ESPを詰まらせないネットワーク・アプリ設計と、事前プロビジョニングでユーザー体験を最適化。
- ラボはやり直しが速い設計(イメージ、テンプレ、スクリプト)に。
この方針で進めれば、Autopilotの検証・本番展開のいずれでも、接続不能の不安を最小化しながら、安定してOOBE~ESP~運用の各段階を通過させることができます。

コメント