PowerShell Remoting(WinRM)入門 ── 複数台のWindowsを一括管理する

· 更新日: · · PowerShell, Windows, WinRM, リモート管理, 自動化, 運用改善, セキュリティ, スクリプト

更新履歴(3件・最終更新 2026年08月02日)

この記事に加えた変更の記録です。アーカイブした更新前のバージョンは、DOI付きの固定URLから読めます。

記事の冒頭に「この記事の知識マップ」節を追加しました。本文で扱っている概念とその関係を、要約・図・詳細ページへのリンクにまとめたものです。本文の主張は変えていません。
外部レビュー(1283件)への対応として本文を更新しました。個々の変更内容は、この下の履歴を参照してください。
つながらないときの切り分けを独立した章として新設し、8ステップの手順と代表的なエラーメッセージの対応表を追加しました。あわせてHTTPSリスナーの構成手順、JEAの説明、前提とする環境を追加しています。
初版公開
この記事を引用する(DOI: 10.5281/zenodo.21590152)

この記事はZenodoにアーカイブされています。常に最新版へ解決されるDOIと、いま表示している版に固定されたDOIの両方を下に示します。

小村 豪(2026)「PowerShell Remoting(WinRM)入門 ── 複数台のWindowsを一括管理する」合同会社小村ソフト. https://doi.org/10.5281/zenodo.21590152 https://staging.comcomponent.com/blog/powershell-remoting-winrm-introduction/

DOI(最新版)
10.5281/zenodo.21590152
DOI(この版)
10.5281/zenodo.21733093

「Windows Updateのあと、サーバー20台が全部ちゃんと起動しているか見てきて」「全拠点のPCで、あの設定値がどうなっているか調べてほしい」── この手の依頼を、リモートデスクトップで1台ずつログインして確認していないでしょうか。1台3分でも20台で1時間。人間は途中で飽きますし、確認漏れも起きます。

PowerShell Remotingは、この「複数台への同じ作業」をコマンド1発に変える仕組みです。WindowsにはWinRMというリモート管理の土台が標準搭載されており、Windows Serverでは既定で有効になっています。つまり多くの現場では、追加ソフトなしで今日から使えます。にもかかわらず「なんとなく怖い」「ワークグループでつながらなかったので諦めた」という声をよく聞きます。

この記事では、中小企業の情シスや運用担当者を対象に、Remotingの仕組み(何がどのポートで動き、誰が接続できるのか)から、Invoke-Commandによる一括実行、ドメイン環境とワークグループ環境の違い、second hop問題のような有名な落とし穴、「つながらない」ときの切り分け、そして「読み取りから始める」安全運用までを整理します。

前提とする環境

  • 接続される側: Windows Server 2012以降のWindows Serverでは、PowerShell Remotingは既定で有効です。1 クライアント版のWindowsではWinRMサービスが既定で無効なので、Enable-PSRemotingでの有効化が必要です。1
  • 接続する側: この記事のコマンド例は、Windows PowerShell 5.1とPowerShell 7のどちらにも存在するコマンドレットだけで書いています。ただしWSMan:ドライブやTest-WSManなどのWS-Management関連コマンドレットはWindows上のPowerShellでのみ使えます(Linux・macOSのPowerShellでは第6章のSSHベースRemotingを使います)。2
  • 権限: リモート側の設定変更(Enable-PSRemoting、TrustedHosts、リスナー)は、いずれも管理者として起動したPowerShellが必要です。1
  • ネットワーク: ドメイン環境とワークグループ環境の両方を扱います。違いは第3章にまとめました。

この記事の知識マップ

この記事は、WinRM(WS-Managementの実装)の上で動くPowerShell Remotingの仕組みと安全な使い方を扱う。Enable-PSRemotingはWinRMサービスの起動・リスナー作成・ファイアウォール例外・セッション構成の有効化を自動化し、ドメイン環境はKerberosによる相互認証でそのまま接続できる一方、ワークグループ環境はNTLM認証となり接続側のTrustedHostsへの登録と明示的な資格情報が必要になるとしている。Invoke-Commandによる一括実行の結果はメソッドを持たないデシリアライズ済みオブジェクトであり、操作はリモート側のScriptBlockで完結させるべきだとする。接続先からさらに別サーバーへ届かないsecond hop問題には、$using:による資格情報の明示的な受け渡しを最も手軽な対処とし、リソースベースのKerberos制約付き委任やJEA、リスクの大きいCredSSPを状況に応じた選択肢として位置づけている。

PowerShell Remoting(WinRM)の知識マップPowerShell RemotingがWinRM上でInvoke-CommandやPSSessionを動かし、ドメインのKerberosとワークグループのNTLM/TrustedHostsで認証経路が分かれ、second hop問題に対して明示的な資格情報渡し・委任・JEA・CredSSPという複数の対処が並ぶ関係を示す図。利用する利用する利用する利用する利用する利用するで確認できる利用する利用する自動化するで構成できるで確認できるで構成できるで構成できる前提とする実装を担う軽減する用いるのは非推奨原因になり得る推奨される対応推奨される対応利用する推奨される対応両立しないPowerShell RemotingWinRM(Windows Remote Management)Invoke-CommandEnter-PSSessionNew-PSSessionSSHベースのPowerShell RemotingCLIXMLシリアライズ/デシリアライズされたオブジェクトTest-WSManKerberosNTLMEnable-PSRemotingWindowsファイアウォールGet-NetFirewallRuleTrustedHostsWinRM HTTPS(5986)リスナー相互認証リソースベースのKerberos制約付き委任second hop(ダブルホップ)問題CredSSPアカウント乗っ取りJEA(Just Enough Administration)$using:スコープ修飾子

図の実線は常に成り立つ関係、破線は条件付きの関係です(成立条件は詳細ページの各関係の説明に記載)。関係すべての一覧(全24件、根拠・確度つき)と主要概念の定義は知識マップ詳細ページにまとめています。データ: JSON-LD / Turtle

1. まず結論

  • PowerShell RemotingはWinRM(WS-Management実装)の上で動き、既定でHTTP 5985 / HTTPS 5986ポートを使います。HTTPでも通信内容は認証プロトコルによるメッセージレベル暗号化がかかります。3
  • 接続できるのは既定でリモート側Administratorsグループのメンバーだけで、セッションは接続ユーザーのコンテキストで動きます。「Remotingを有効にしたら誰でも入れる」わけではありません。3
  • Enable-PSRemotingがやることは明確に定義されています。WinRMサービスの開始と自動起動化、リスナー作成、ファイアウォール例外、セッション構成の有効化です。Windows Serverでは既定で有効、クライアントWindowsでは手動で有効化します。43
  • ドメイン環境はKerberosでそのまま動き、ワークグループはNTLM + TrustedHosts + 明示的な資格情報が必要です。TrustedHostsは「相手を信頼する」設定ではなく「相手の身元確認を諦めるリスト」なので、最小限に絞ります。53
  • 一括実行はInvoke-Command、対話操作はEnter-PSSession、状態を保って何度も使うならNew-PSSessionです。Invoke-Commandは既定で同時32台まで並列に処理します。67
  • リモートから返ってくるのはデシリアライズされたオブジェクトで、メソッドがありません。操作はScriptBlockの中(リモート側)で完結させ、手元では結果の集計だけを行います。87
  • 接続先からさらに別のサーバーへはアクセスできません(second hop問題)。これは欠陥ではなく、資格情報をリモートへ送らない安全設計の帰結です。対処方法は複数あり、要件で選びます。9
  • PowerShell 7ではSSHベースのRemotingも使えます。Linuxとの相互管理が必要な場合や、WinRMを開けたくない環境の選択肢になります。2

2. 仕組み ── WinRMの上で、誰が、どう入るのか

PowerShell Remotingの土台はWinRM(Windows Remote Management)です。WinRMは標準プロトコルWS-ManagementのMicrosoft実装で、PowerShell RemotingはこのWinRM経由でリモートコンピューター上のPowerShellにコマンドを届けます。3 通信は既定でHTTP 5985番、HTTPS 5986番ポートを使います。35

「HTTPで平文なのでは」と心配されますが、初回認証の完了後はWinRMが通信を暗号化します。HTTPSではTLS、HTTPでは認証プロトコルがネゴシエートしたメッセージレベル暗号化(Kerberosなら現代の環境でAES-256)です。3 また、接続できるのは既定でリモート側のAdministratorsグループのメンバーだけで、セッションは接続したユーザーのコンテキストで実行されるため、ファイルやレジストリへのアクセス制御は普段どおり適用されます。3

受け側の準備はEnable-PSRemotingです。このコマンドレットが何をするかは公式に列挙されています。内部でSet-WSManQuickConfigを実行し、(1)WinRMサービスの開始、(2)スタートアップ種別の自動化、(3)任意のIPアドレスで受けるリスナーの作成、(4)WS-Management通信のファイアウォール例外の有効化、(5)セッション構成(エンドポイント)の作成・有効化とリモートアクセス許可、を行ったうえでWinRMサービスを再起動します。4

# 接続「される」側で、管理者権限のPowerShellから1回だけ実行する
# (Windows Serverでは既定で有効なので通常は不要。クライアントWindowsで必要)
Enable-PSRemoting

# 接続「する」側からの疎通確認 ── これが通ればRemotingの土台はできている
Test-WSMan -ComputerName sv-app01

2つ、知らないとハマる仕様があります。第一にファイアウォールです。サーバー版WindowsではEnable-PSRemotingがパブリックネットワーク向けにも「同一サブネットからのみ許可」の規則を作りますが、クライアント版ではネットワークプロファイルがパブリックだと有効化自体がエラーになります(検証機を社内Wi-Fiにつないだときの定番トラブルです)。この場合は-SkipNetworkProfileCheckを付けるか、プロファイルをプライベートに直します。4

第二にPowerShellのバージョンとエンドポイントの関係です。Enable-PSRemotingは「実行したPowerShellのバージョン用」のエンドポイントを構成します。PowerShell 7で実行してもWindows PowerShell 5.1のエンドポイントには影響せず、逆も同様です。4 しかもPowerShell 7から接続しても、既定ではWindows PowerShell 5.1の既存エンドポイント(Microsoft.PowerShell)が使われるため10、「手元は7なのに、リモートで動いているのは5.1だった」はごく普通に起きます。リモート側で$PSVersionTableを表示して確認する癖をつけてください。

3. ドメインとワークグループ ── 認証の壁はここにある

Remotingの入門でつまずく最大のポイントは、コマンドの文法ではなく認証です。環境によって必要な準備が変わります。

項目 ドメイン環境 ワークグループ環境
認証プロトコル Kerberos(相互認証あり)5 NTLM(サーバーの身元検証なし)5
追加設定 原則不要。コンピューター名でそのまま接続 接続側でTrustedHostsへの登録が必要5
資格情報 ログオン中のユーザーがそのまま使われる -Credentialで明示指定が基本
IPアドレス指定 TrustedHosts登録またはHTTPSが必要11 同左

ドメイン環境ならKerberosによる相互認証(クライアントもサーバーも互いを検証)が働くため、Invoke-Command -ComputerName sv-app01 { ... } がそのまま通ります。ワークグループではKerberosが使えないため5、接続側のTrustedHostsに相手を登録します。

# 接続「する」側で、管理者として起動したPowerShellから実行(ワークグループのみ必要)
# TrustedHostsの変更にも管理者権限が要る。既存の値は上書きされるので、まず現在値を確認する
Get-Item WSMan:\localhost\Client\TrustedHosts

# 必要最小限のホスト名だけを追記する。-Concatenateなしだと既存の登録が消える。'*'での全許可は避ける
Set-Item WSMan:\localhost\Client\TrustedHosts -Value 'sv-app01,sv-app02' -Concatenate

# 資格情報を明示して接続テスト
$cred = Get-Credential sv-app01\Administrator
Invoke-Command -ComputerName sv-app01 -Credential $cred -ScriptBlock { hostname }

ここで重要なのがTrustedHostsの意味です。公式ドキュメントは「TrustedHostsに載せたコンピューターは認証されず、クライアントが資格情報を送ってしまう可能性がある」と明記しています。5 つまりこれは「信頼できる相手のリスト」というより、「サーバーの身元を検証できないという警告を抑止するリスト」です。3 DNSやARPを細工された環境では、偽サーバーに管理者資格情報を渡すリスクがあります。だからワイルドカード登録を避け、固定のホスト名・IPを最小限だけ載せる。本格運用するワークグループ環境やDMZでは、証明書を用意してHTTPS(5986)リスナーを構成する方が筋が良い、というのが実務の判断です。3

なお、Get-Credentialで受け取った資格情報をスクリプトに平文で書き始めたら黄信号です。資格情報の保存と受け渡しの定石は、同時公開の「PowerShellで資格情報を安全に扱う」にまとめています。

ワークグループでもうひとつ見落としやすいのがパスワードの有無です。接続先のアカウントにパスワードが設定されていない(空パスワード)場合、リモートコマンドは実行できません。1

3.1. HTTPS(5986)リスナーを構成する

ワークグループやDMZで常用するなら、TrustedHostsで済ませずHTTPSリスナーを立てます。手順の骨子はこうです。12

  1. サーバー認証用の証明書を用意する。要件は「ローカルコンピューターのサーバー認証証明書であること」「CN(またはサブジェクト代替名)がホスト名と一致すること」「有効期限内で、失効しておらず、自己署名でないこと」です。社内CAがあればhttps://<証明機関のサーバー>/certsrvのWeb登録から要求できます。
  2. 証明書をローカルコンピューターの個人ストアに入れる。確認は証明書スナップイン(MMCで「証明書」を追加し、ウィザードで「コンピューター アカウント」を選ぶ)の 証明書(ローカル コンピューター) > 個人 > 証明書 です。
  3. HTTPSリスナーを作る。手軽なのは次の1行です。

     winrm quickconfig -transport:https
    

    証明書が複数あってどれを使うか明示したい場合は、PowerShellから拇印を指定して作ることもできます(拇印はGet-ChildItem Cert:\LocalMachine\Myで確認できます)。

     New-Item -Path WSMan:\localhost\Listener -Address * -Transport HTTPS -CertificateThumbPrint '証明書の拇印' -Force
    
  4. ファイアウォールでTCP 5986の受信を許可する。Enable-PSRemotingが作る規則はHTTP(5985)向けなので、HTTPSは別途必要です。
  5. リスナーができたか確認する。

     winrm enumerate winrm/config/listener
    

接続する側は-UseSSLを付けるだけです。

Invoke-Command -ComputerName sv-app01.example.local -UseSSL -Credential $cred -ScriptBlock { hostname }

証明書の条件を満たしていないと、リスナー作成時に「Cannot create a WinRM listener on HTTPS because this machine does not have an appropriate certificate.(エラー番号 -2144108267 / 0x80338115)」というエラーになります。この場合は証明書の有効期限、発行先がホスト名と一致しているか、拡張キー使用法に「サーバー認証」が含まれているか、証明のパスが有効かを順に確認します。12

4. Invoke-Command ── 「20台に同じことをする」の基本形

Remotingの主役はInvoke-Commandです。-ComputerNameに複数台を渡し、-ScriptBlockに「リモートでやること」を書きます。6 まずは読み取り専用の棚卸しから始めるのが安全運用の鉄則です。

$servers = 'sv-app01', 'sv-app02', 'sv-db01'

# パッチ適用後の状態確認 ── 読み取りだけなので安心して流せる
$result = Invoke-Command -ComputerName $servers -ScriptBlock {
    # このブロックの中は「リモート側」で実行される
    $os = Get-CimInstance Win32_OperatingSystem
    [PSCustomObject]@{
        LastBoot   = $os.LastBootUpTime                      # 再起動が済んだか
        SpoolerRun = (Get-Service -Name Spooler).Status      # 業務に必要なサービスの状態
        FreeGB     = [math]::Round((Get-PSDrive C).Free / 1GB, 1)
    }
}

# どの結果がどのサーバーのものかはPSComputerNameで分かる
$result | Sort-Object PSComputerName |
    Select-Object PSComputerName, LastBoot, SpoolerRun, FreeGB |
    Export-Csv -Path .\patch-check.csv -NoTypeInformation -Encoding UTF8

各サーバーへの接続は並列に処理され、既定の同時実行数(ThrottleLimit)は32です。7 結果は届いた順に混ざって返るため、上の例のように自動付与されるPSComputerNameプロパティで並べ直します。8

4.1. 変数の渡し方 ── $using: と -ArgumentList

ScriptBlockはリモートで実行されるので、手元の変数はそのままでは見えません。値を持ち込む方法は2つあります。13

$threshold = (Get-Date).AddDays(-30)

# 方法1: $using: ── 呼び出し側の変数の「値のコピー」をリモートに埋め込む
Invoke-Command -ComputerName $servers -ScriptBlock {
    (Get-ChildItem 'D:\AppLogs' -Filter *.log |
        Where-Object LastWriteTime -lt $using:threshold).Count
}

# 方法2: -ArgumentList ── ScriptBlock側のparamで受け取る(引数が多いときに読みやすい)
Invoke-Command -ComputerName $servers -ScriptBlock {
    param($limit)
    (Get-ChildItem 'D:\AppLogs' -Filter *.log |
        Where-Object LastWriteTime -lt $limit).Count
} -ArgumentList $threshold

$using:で渡る値はリモート側では独立したコピーです。リモート側で書き換えても手元の変数は変わりません。13

4.2. 返ってくるのは「スナップショット」── デシリアライズされたオブジェクト

Remotingの結果で最初に戸惑うのがこれです。生きた.NETオブジェクトはネットワークを越えられないため、リモートの出力はXML(CLIXML)にシリアライズされて送られ、手元でデシリアライズされたオブジェクトに復元されます。これは実行時点のプロパティのスナップショットで、メソッドを持ちません。87

たとえばGet-Serviceの結果をローカルで受けて.Stop()を呼ぶことはできません。サービスを止めたいなら、ScriptBlockの中でStop-Serviceを実行する── つまり操作はリモート側で完結させ、手元に持ち帰るのは報告用のデータだけ、と役割を分けるのが正しい形です。プロパティの選別・整形・CSV化といった手元での加工は普段のPowerShellと同じ感覚で行えます(このあたりの基本操作は「PowerShellコマンドの基本」を参照してください)。

5. Enter-PSSessionとNew-PSSession ── 対話と使い回し

1台を対話的に調べたいときはEnter-PSSessionです。プロンプトが[sv-app01]: PS>に変わり、入力したコマンドがリモートで実行されます。exitで抜けます。11 リモートデスクトップと違って画面は持ち込まれませんが、「ログを見る」「設定を確認する」程度ならこちらの方が速く、接続にもAdministratorsグループのメンバーであることが必要なのは同じです。11

一方、Invoke-Commandを-ComputerNameで呼ぶたびに、接続の確立と破棄が毎回行われます。14 同じサーバー群に何度もコマンドを投げる調査作業では、New-PSSessionで持続的なセッションを作って使い回すと速く、しかもリモート側の変数や状態がコマンド間で保持されます。1415

# セッションを一度だけ張り、変数$sで使い回す
$s = New-PSSession -ComputerName $servers
try {
    # 1回目: リモート側に$hotfixという変数を作る
    Invoke-Command -Session $s { $hotfix = Get-HotFix | Sort-Object InstalledOn -Descending }

    # 2回目: 前のコマンドで作った変数がそのまま使える(セッションが状態を保持している)
    Invoke-Command -Session $s { $hotfix | Select-Object -First 5 }
}
finally {
    # 途中でエラーや中断があっても必ず破棄する(リモート側のリソースを解放する)
    Remove-PSSession $s
}

6. 落とし穴 ── second hop、そしてSSHという選択肢

6.1. second hop(ダブルホップ)問題

現場で最も有名な壁がこれです。手元のPC(A)からサーバーBにRemotingで入り、Bの中から\\fs01\share(サーバーC)を読もうとするとアクセス拒否になります。既定のKerberos/NTLM認証は資格情報そのものをBへ送らずに認証する安全な方式のため、Bはあなたの代理としてCへ認証できないのです。39

対処は複数あり、公式ドキュメントが推奨順に整理しています。9 主なものだけ挙げると次のとおりです。

  • ScriptBlock内で資格情報を明示的に渡す ── サーバー側の構成変更が不要で最も手軽。$using:credで内側のInvoke-Commandに資格情報を渡します。9 ただし資格情報オブジェクトが中継サーバー(B)のセッションに渡る以上、Bが侵害されていれば渡した資格情報も使われうるため、Bを完全に信頼できる場合に限り、渡すアカウントもC側で必要最小限の権限を持つ専用アカウントにするのが前提です。
  • リソースベースのKerberos制約付き委任 ── 資格情報を保存せず、アクセス先(C)側で「Bからの委任を受ける」と構成する方式。ドメイン管理者権限なしで構成でき、セキュリティと構成の簡単さのバランスが良い選択肢です。9
  • JEA(Just Enough Administration) ── 「その業務に必要なコマンドだけ」を許可した専用のエンドポイントを用意し、権限を絞り込むPowerShellの仕組みです。仮想アカウントを使う構成にすれば、利用者は管理者以外の資格情報で接続しながら、許可された管理コマンドだけを実行できます。16 second hopの文脈では、中継サーバー(B)に管理者資格情報を配る代わりに、Cへのアクセスを含む定型作業だけを実行できる窓口を作る、という使い方になります。9
  • CredSSP ── 資格情報がリモートサーバーにキャッシュされるため、そのサーバーが侵害されると資格情報ごと盗まれます。既定で無効であり、有効化は最も信頼できる環境に限定すべきです。9
# 最も手軽な回避: 内側のInvoke-Commandに$using:credで資格情報を渡す
# 外側(sv-app01)へは自分自身の資格情報で接続し、内側に渡すのはfs01側で
# 必要最小限の権限を持つ専用アカウントだけにする(管理者の資格情報を配らない)
#
# 【前提】内側の呼び出しは「sv-app01からfs01への新しいRemoting接続」なので、次が要る:
#   1. sv-app01からfs01へWinRM(5985/5986)が到達できること
#   2. ワークグループやIPアドレス指定なら、sv-app01側のTrustedHostsにfs01が登録済みであること
#   3. $credがfs01で有効なアカウント(ドメインアカウント、またはfs01のローカルアカウント)であること
# これらを確認せずにコピペすると「手元では動くのに中継サーバーからは失敗する」になりがち
$cred = Get-Credential CONTOSO\svc-fileread
Invoke-Command -ComputerName sv-app01 -ScriptBlock {
    Invoke-Command -ComputerName fs01 -Credential $using:cred -ScriptBlock { hostname }
}

そもそも「Bを経由してCのファイルを読む」のではなく、手元からC相手に直接Invoke-Commandする構成にできないかを先に考えるのが、いちばん安い解決策です。

6.2. PowerShell 7ならSSHベースのRemotingも選べる

PowerShell 6.0以降は、WinRMの代わりにSSHで接続するRemotingが使えます。Invoke-Command / Enter-PSSession / New-PSSessionに-HostName、-UserName、-KeyFilePathというSSH用のパラメーターセットが追加されており、WindowsとLinuxをまたいだ管理ができます。2 接続先にはSSHサーバーとPowerShellのSSHサブシステム構成が必要で、WinRMベースにあるエンドポイント構成やJEAのような機能は現状サポートされません。2 Linuxサーバーが混在する環境や、鍵認証で運用を統一したい場合の選択肢として覚えておくとよいでしょう。Windows PowerShell 5.1にはこの機能はないので、必要なら移行の動機になります(違いの全体像は同時公開の「Windows PowerShell 5.1とPowerShell 7の違い」を参照)。

ちなみに、RemotingのセッションはRDPのようなデスクトップセッションを作りません。「リモートで動く」という意味が両者でどう違うかは「Windowsのセッション分離をどう理解するか」で整理しています。

7. つながらないときの切り分け

入門者がRemotingを諦める理由の大半は「つながらない」です。しかも失敗の原因は、サービス・リスナー・ファイアウォール・認証・権限のどこにでもありえます。上流から順に潰していくと迷いません。

7.1. 切り分けの順番

  1. 疎通を見る。まず接続する側からTest-WSMan -ComputerName sv-app01。ここが通れば、WinRMサービス・リスナー・ファイアウォールまでは生きています(認証や権限の問題は残ります)。通らなければ以下へ。
  2. リモート側でWinRMサービスが動いているか。サーバー版はスタートアップ種別が自動ですが、クライアント版のWindowsではWinRMサービスが既定で無効です。1 Get-Service WinRMで確認し、必要ならEnable-PSRemoting(サービス起動・自動起動化・リスナー・ファイアウォール例外・セッション構成をまとめて構成)を実行します。4
  3. リスナーが待ち受けているか。リモート側で次を実行し、ListeningOnが空でないかを見ます。空の場合は、グループポリシーでリスナーを配っている環境での設定ミスが定番です。1

     Get-WSManInstance winrm/config/listener -Enumerate
    
  4. ネットワークプロファイルを見る。クライアント版でネットワークがパブリックだと、Enable-PSRemoting自体が「Unable to check the status of the firewall」で失敗します。プロファイルをプライベートに直すか、-SkipNetworkProfileCheckを付けます。1
  5. ファイアウォール規則を見る。サーバー版でもパブリックプロファイルでは「同一サブネットからのみ許可」の規則になります。別サブネットから入るなら規則の見直しが要ります(Get-NetFirewallRuleで規則名を確認してから変更してください。規則名はWindowsのバージョンで異なります)。1
  6. 認証方式の条件を満たしているか。ワークグループ、非ドメイン参加、IPアドレス指定の場合はKerberosが使えずNTLMになるため、TrustedHostsへの登録(またはHTTPS)と-Credentialの明示指定が必須です。接続先アカウントに空パスワードは使えません。1
  7. 接続できる権限があるか。既定のエンドポイントに接続できるのはリモート側Administratorsのメンバーだけです。別ドメインのユーザーやローカルアカウントは、既定では標準ユーザーのトークンになるため、管理者として振る舞えません(必要ならLocalAccountTokenFilterPolicyですが、UACのリモート制限を全ユーザーに対して無効化する設定なので影響を理解したうえで)。1
  8. エンドポイントのPowerShellバージョンを確認する。つながったのに「そのコマンドレットがない」と言われるときは、第2章のとおりWindows PowerShell 5.1側のエンドポイントに入っている可能性があります。Invoke-Command -ComputerName sv-app01 { $PSVersionTable.PSVersion }で確かめ、必要なら-ConfigurationNameで明示します。10

7.2. 代表的なエラーメッセージの読み方

エラー文はほぼ定型なので、覚えるというより「この文言ならここを見る」と対応づけておくのが実用的です。1

エラーメッセージ(抜粋) よくある原因 最初に見るところ
Access is denied. You need to run this cmdlet from an elevated process. 手元のPowerShellが管理者権限でない 「管理者として実行」で開き直す
ACCESS IS DENIED 接続先でRemotingが無効/接続ユーザーがAdministratorsでない/別ドメイン・ローカル管理者のトークン制限 接続先でEnable-PSRemoting-Credentialで管理者を指定、必要ならセッション構成の権限やLocalAccountTokenFilterPolicy
The connection to the remote host was refused. Verify that the WS-Management service is running on the remote host and configured to listen for requests on the correct port and HTTP URL. WinRMサービスが停止、リスナーがない、ポートが違う Get-Service WinRM、リスナーの列挙、ポート設定
The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. リスナーのListeningOnが空(ポリシー設定ミス)、プロキシの影響 リスナーの列挙、New-PSSessionOptionのプロキシ設定
The WinRM client cannot process the request. If the authentication scheme is different from Kerberos, or if the client computer is not joined to a domain, then HTTPS transport must be used or the destination machine must be added to the TrustedHosts configuration setting. ワークグループ、非ドメイン参加、IPアドレス指定 TrustedHostsへの登録+-Credential、または3.1のHTTPS構成
Unable to check the status of the firewall(Enable-PSRemoting実行時) クライアント版でネットワークがパブリック プロファイルをプライベートへ、または-SkipNetworkProfileCheck
The WS-Management service cannot complete the operation within the time specified in OperationTimeout. 処理が長い、相手が高負荷 New-PSSessionOption -OperationTimeoutで延長
The total data received from the remote client exceeded allowed maximum. 返しているデータが大きすぎる ScriptBlockの中で集計・選別してから返す。必要ならクォータを調整

切り分けのコツは、「手元の問題か、経路の問題か、相手の問題か」を1つずつ確定させることです。Test-WSManが通るかどうかで経路と相手のサービスまでを切り分け、通ったあとのエラーは認証と権限の話に絞る。この2段構えにすると、原因不明のまま設定をいじり回すことがなくなります。

8. 実務の定石(判断表)

論点 選択肢 判断の目安
1台を対話的に調べる RDP / Enter-PSSession 画面が必要ならRDP、コマンドで済むならEnter-PSSessionが軽い11
複数台に同じ処理 1台ずつ手作業 / Invoke-Command 3台を超えたらInvoke-Command。既定で32台まで並列67
何度もコマンドを投げる -ComputerName都度接続 / New-PSSession再利用 調査で対話的に往復するならセッション再利用。終わったらRemove-PSSession14
ワークグループの認証 TrustedHosts(HTTP) / HTTPSリスナー 一時利用は最小限のTrustedHosts。常用するならHTTPS構成(手順は3.1)5312
second hop対処 資格情報を明示的に渡す / リソースベース委任 / CredSSP まず構成変更不要な明示渡し。恒常的ならリソースベース委任。CredSSPは最終手段9
最初に流すコマンド 変更系 / 読み取り系 必ずGet系で棚卸しから。変更系は-WhatIf対応コマンドで予行してから本実行

最後の行は強調しておきます。Invoke-Commandは「20台を一瞬で直すコマンド」であると同時に「20台を一瞬で壊すコマンド」です。幸い、Stop-ServiceやSet-ItemPropertyのような変更系コマンドレットの多くは-WhatIfに対応しており、ScriptBlockの中でもそのまま使えます。新しいスクリプトはまず1台に、次に-WhatIf付きで全台に、最後に本実行という三段階を習慣にすると、事故率が目に見えて下がります。

9. まとめ

  • RemotingはWinRM(WS-Management)上で動き、既定ポートはHTTP 5985 / HTTPS 5986。接続できるのは既定でリモート側Administratorsのメンバーだけで、通信は認証後に暗号化されます。
  • Enable-PSRemotingはWinRMサービス起動・リスナー作成・ファイアウォール例外・セッション構成有効化を行います。実行したPowerShellのバージョン用のエンドポイントが構成される点に注意してください。
  • ドメインはKerberosでそのまま、ワークグループはTrustedHosts + 明示的資格情報。TrustedHostsは身元検証の放棄リストなので最小限に。
  • 一括実行はInvoke-Command(既定32並列)、対話はEnter-PSSession、状態を保つならNew-PSSessionの再利用。結果はメソッドを持たないデシリアライズ済みオブジェクトなので、操作はリモート側で完結させます。
  • 接続先からさらに先へは届きません(second hop)。まず資格情報の明示渡し、恒常運用ならリソースベースのKerberos制約付き委任を検討します。
  • 「つながらない」ときは、Test-WSManで経路と相手のサービスまでを切り分けてから、認証(TrustedHosts・資格情報)と権限(Administrators)に絞って見ます。代表的なエラー文と対応先は第7章の表にまとめました。
  • 運用はまず読み取り系から。変更系は1台 → -WhatIf → 本実行の三段階で。ファイルサーバーの棚卸しに応用する具体例は同時公開の「PowerShellでファイルサーバーを棚卸しする」をどうぞ。

関連記事

関連する相談領域

合同会社小村ソフトでは、PowerShellによるサーバー・クライアントの一括管理の仕組みづくり、Remotingを組み込んだ運用スクリプトの設計・レビュー、「つながらない」「特定環境でだけ認証に失敗する」といったWinRM/認証まわりの調査を扱っています。

参考リンク

  1. Microsoft Learn, about_Remote_Troubleshooting. Windows Server 2012以降のWindows ServerではRemotingが既定で有効なこと、クライアント版WindowsではWinRMサービスが既定で無効なこと、WSMan:ドライブの設定変更に管理者権限が必要なこと、代表的なエラーメッセージ(Access is denied/接続拒否/Unable to check the status of the firewall/TrustedHostsとHTTPSに関するWinRMクライアントのエラー/タイムアウト/クォータ超過)とその対処、Get-WSManInstanceによるリスナー列挙とListeningOnが空になるポリシー設定ミス、パブリックネットワークでのファイアウォール規則の挙動、ワークグループでは空パスワードのアカウントが使えないこと、別ドメイン・ローカルアカウントの管理者に対するトークン制限とLocalAccountTokenFilterPolicyについて。  2 3 4 5 6 7 8 9 10 11

  2. Microsoft Learn, PowerShell remoting over SSH. PowerShell 6以降でSSHベースのRemotingが使えること、New-PSSession/Enter-PSSession/Invoke-Commandに-HostName/-UserName/-KeyFilePathパラメーターセットが追加されたこと、マルチプラットフォームで動作すること、エンドポイント構成やJEAは現状サポートされないことについて。  2 3 4

  3. Microsoft Learn, Security Considerations for PowerShell Remoting using WinRM. RemotingがWinRM(WS-ManagementのMicrosoft実装)を使うこと、既定ポートがHTTP 5985/HTTPS 5986であること、既定でAdministratorsグループのメンバーのみ接続可能でセッションがユーザーのコンテキストで動くこと、認証後の通信が暗号化されること、TrustedHostsが身元検証エラーの抑止リストにすぎないこと、second hop問題の背景について。  2 3 4 5 6 7 8 9 10 11 12

  4. Microsoft Learn, Enable-PSRemoting. Enable-PSRemotingが行う操作の一覧(WinRMサービス開始・自動起動化、リスナー作成、ファイアウォール例外、セッション構成の有効化とセキュリティ記述子変更)、Windows Serverでは既定で有効なこと、クライアント版のパブリックネットワークでの制限とSkipNetworkProfileCheck、実行したバージョン用のエンドポイントが構成されることについて。  2 3 4 5

  5. Microsoft Learn, Installation and configuration for Windows Remote Management. WinRM 2.0の既定リスナーポートが5985/5986であること、ドメインアカウントにはKerberos・ローカルアカウントにはNTLMが選択されること、Kerberosがワークグループでは使えずドメインのみであること、TrustedHostsのコンピューターは認証されず資格情報が送られる可能性があるため最小限にすべきことについて。  2 3 4 5 6 7 8

  6. Microsoft Learn, Invoke-Command. Invoke-Commandが単一コマンドで複数のコンピューターにコマンドを実行できること、-ComputerNameによる一時接続と-SessionによるPSSession利用の使い分け、-ArgumentListや-FilePathなどのパラメーターについて。  2 3

  7. Microsoft Learn, PowerShell Remoting FAQ. 同時接続数の既定値が32でThrottleLimitパラメーターで変更できること、リモートコマンドの出力がCLIXMLへシリアライズされデシリアライズ済みオブジェクト(メソッドなし)として返ること、Invoke-Commandの結果に由来判別用のプロパティが付くことについて。  2 3 4 5

  8. Microsoft Learn, about_Remote_Output. リモートコマンドの出力がシリアライズ/デシリアライズを経てプロパティのみのスナップショットになること、結果が届いた順に返るためPSComputerNameで並べ替えられることについて。  2 3

  9. Microsoft Learn, Making the second hop in PowerShell Remoting. second hop問題のシナリオ、対処方法の一覧と推奨順(CredSSP、リソースベースのKerberos制約付き委任、JEAなど)、CredSSPが資格情報をリモートにキャッシュするため侵害時のリスクがあり既定で無効なこと、ScriptBlock内で$Using:credにより資格情報を渡す例について。  2 3 4 5 6 7 8

  10. Microsoft Learn, Migrating from Windows PowerShell 5.1 to PowerShell 7. WinRMが有効な環境ではPowerShell 7が既定でWindows PowerShell 5.1の既存エンドポイント(Microsoft.PowerShell)を使って接続すること、PowerShell 7自身のエンドポイントを作るにはEnable-PSRemotingを実行することについて。  2

  11. Microsoft Learn, Enter-PSSession. Enter-PSSessionが単一のリモートコンピューターとの対話セッションを開始すること、exit/Exit-PSSessionで終了すること、リモート側Administratorsグループのメンバーである必要があること、IPアドレス指定時はHTTPS構成またはTrustedHosts登録が必要なことについて。  2 3 4

  12. Microsoft Learn, How to configure WINRM for HTTPS (KB 2019527). HTTPSリスナーに必要な証明書の要件(ローカルコンピューターのサーバー認証証明書、CNがホスト名と一致、期限切れ・失効・自己署名でないこと)、証明書スナップインでの確認手順、winrm quickconfig -transport:httpsによる構成、winrm enumerate winrm/config/listenerによる確認、Windows 7以降のHTTP 5985/HTTPS 5986というポート、適切な証明書がない場合のエラー0x80338115と確認すべき証明書の属性について。  2 3

  13. Microsoft Learn, about_Remote_Variables. リモート実行されるコマンドでローカル変数を使うための$using:スコープ修飾子、リモートセッションでは値が独立したコピーとして渡ること、シリアライズによりメソッドが失われることについて。  2

  14. Microsoft Learn, New-PSSession. New-PSSessionが持続的な接続(PSSession)を作成すること、データを共有する複数コマンドの実行に使うこと、-ComputerName指定では一時接続が作られてコマンドごとに閉じられること、SSHベースの接続もサポートすることについて。  2 3

  15. Microsoft Learn, Running Remote Commands. Invoke-Commandによるスクリプトファイル実行(-FilePath)、New-PSSessionで作った持続的セッションでは変数などの状態がコマンド間で保持されることについて。 

  16. Microsoft Learn, Overview of Just Enough Administration (JEA). JEAがPowerShellで管理するものに対する委任管理を可能にするセキュリティ技術であること、実行できるコマンドレット・関数・外部コマンドを限定できること、仮想アカウントやグループ管理サービスアカウントにより管理者アカウントの数を減らせること、トランスクリプトとログで実行内容を把握できることについて。 

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

この記事は次のサービスページにつながります。近い入口からご覧ください。

よくある質問

この記事のテーマについて、相談時によくある質問をまとめています。

Enable-PSRemotingを実行すると何が起きますか?
内部でSet-WSManQuickConfigが実行され、WinRMサービスの開始とスタートアップの自動化、任意のIPアドレスで要求を受けるリスナーの作成、WS-Management通信のファイアウォール例外の有効化、セッション構成(エンドポイント)の有効化とリモートアクセス許可への変更が行われます。Windows Serverでは既定で有効ですが、クライアントWindowsでは自分で実行する必要があります。接続を受ける側だけに必要で、接続する側では実行不要です。
ワークグループ環境(ドメインなし)でPowerShell Remotingを使うには何が必要ですか?
ドメインがないとKerberos認証が使えないため、NTLM認証になります。接続する側で接続先をWSManのTrustedHostsリストに登録し、-Credentialで資格情報を明示的に渡すのが基本形です。ただしTrustedHostsに載せた相手は認証(なりすまし検証)されないまま資格情報が送られる可能性があるため、ワイルドカードではなく必要最小限のホスト名だけを登録し、可能ならHTTPS(5986)リスナーの構成を検討してください。
Invoke-Commandの結果オブジェクトでメソッドが呼べないのはなぜですか?
リモートコマンドの出力はネットワーク越しに送るためにXML(CLIXML)へシリアライズされ、手元ではデシリアライズされたオブジェクトとして復元されるからです。これは実行時点のプロパティのスナップショットであり、生きたオブジェクトではないためメソッドを持ちません。サービスの停止のような操作はローカル側でメソッドを呼ぶのではなく、ScriptBlockの中(リモート側)で実行する必要があります。
second hop(ダブルホップ)問題とは何ですか?
PC AからサーバーBにRemotingで入り、Bからさらに別のサーバーC(ファイルサーバーなど)へアクセスしようとすると拒否される問題です。既定のKerberos/NTLM認証は資格情報そのものをBへ送らないため、BはあなたとしてCへ認証できません。対処には、ScriptBlock内で資格情報を明示的に渡す方法、リソースベースのKerberos制約付き委任、CredSSP(資格情報がリモート側に渡るためリスク増)などがあり、要件に応じて選びます。
PowerShell Remotingには誰でも接続できてしまうのですか?
いいえ。既定ではリモートコンピューターのAdministratorsグループのメンバーだけが接続できます。また、接続後のセッションは接続したユーザーのコンテキストで動くため、OSのアクセス制御はそのまま適用されます。とはいえ管理者にとっては強力な入口なので、ファイアウォール規則の見直し、HTTPSリスナー、必要な管理者だけへの限定といった多層の防御と組み合わせて運用してください。

著者プロフィール

記事の著者プロフィールページです。

小村 豪

合同会社小村ソフト 代表

Windows ソフト開発、技術相談、不具合調査を中心に、既存資産が残る案件や原因が見えにくい障害調査に強みがあります。

ブログ一覧に戻る