Server CoreのWindowsサーバインスタンスにCLIでリモート接続

クラウド上のWindowsサーバにリモート接続するには、RDP(リモートデスクトップ)を利用することが多いでしょう。AWSのEC2においても、Windowsのインスタンスを作成した場合デフォルトでTCPの3389が空いているセキュリティグループが作成され、RDPによる接続ができるようになっています。

Server CoreのWindowsサーバに対してもRDPで接続することはできますが、せっかくのServer Coreなので、CLIで接続したいものです。特に、XのインストールしていないLinuxからWindowsに接続するには、CLI以外の方法はありません。

CLIで接続するには、主に4つの方法があります。

  • WinRS / WinRM
  • Powershell Remoting over WinRM
  • SSH
  • Powershell Remoting over SSH

1. WinRS / WinRM

WinRSは、WinRM(Windows Remote Management)のコマンドラインツールでWindowsにデフォルトでインストールされていますが、Windows環境でしか利用できません。LinuxやmacOS、WSLでは利用できません。

WinRMは、HTTPとHTTPSをサポートしており、それぞれTCPポートの5985と5986を使用します。しかし、HTTPS利用の場合サーバ側に証明書を導入する必要があり手間がかかってしまいます。HTTPでの通信であっても通信の中身をきちんと暗号化してくれます(ドメイン環境ではKerberos/AES-256、それ以外はNTLM/RC4で)ので、通常HTTPを選択しても問題ありません。Windows Server 2022でも、デフォルトでHTTPのみ有効になっています。しかし、セキュリティにシビアな環境での利用はHTTPSを選択したほうが無難でしょう。

一方、HTTP利用の場合クライアント側で明示的にサーバのIPアドレスを信頼ホスト(TrustedHost)に追加する必要があります。ここではHTTPで接続する場合の手順を説明します。

AWS側の設定

AWSでは、インスタンスに対して「WinRM-HTTP(5985番ポート)」もしくは「WinRM-HTTPS(5986番ポート)」を開放します。

サーバ側の設定

Windows ServerはデフォルトでWinRMのサービスが立ち上がっており有効になっています。また、ファイアウォールのPrivateとDomainプロファイルにおいて、下記のようにWinRMのポートが開放済みの状態です。そのため、ドメイン環境であればサーバに一度もログインしなくてもリモート接続は可能です。

PS C:\Users\Administrator> Get-NetFirewallRule -Name 'WINRM-HTTP-In-TCP'


Name                          : WINRM-HTTP-In-TCP
DisplayName                   : Windows Remote Management (HTTP-In)
Description                   : Inbound rule for Windows Remote Management via WS-Management. [TCP 5985]
DisplayGroup                  : Windows Remote Management
Group                         : @FirewallAPI.dll,-30267
Enabled                       : True
Profile                       : Domain, Private
Platform                      : {}
Direction                     : Inbound
Action                        : Allow
EdgeTraversalPolicy           : Block
LooseSourceMapping            : False
LocalOnlyMapping              : False
Owner                         :
PrimaryStatus                 : OK
Status                        : The rule was parsed successfully from the store. (65536)
EnforcementStatus             : NotApplicable
PolicyStoreSource             : PersistentStore
PolicyStoreSourceType         : Local
RemoteDynamicKeywordAddresses : {}

しかしPublicプロファイルではこのポートが開放されていないため、インターネット越しなどドメイン以外の環境の場合、下記コマンドでポートを開放しておく必要があります。いったんRDPでログインしてから、コマンドを実行します。

Set-NetFirewallRule -Name 'WINRM-HTTP-In-TCP' -Profile Domain,Public,Private

クライアント側の設定

HTTPの場合クライアント側の信頼ホスト(TrustedHost)を設定する必要がありますが、残念ながら設定用のコマンドはWinRMのサービスが起動しないとエラーを吐きます。クライアント側の設定をするのにサービスを起動しなければならないのは非常におかしいので、マイクロソフトが別の方法を用意してくれています:直接レジストリをいじる方法です。

ただし、レジストリをいじることは、特にエンタープライズ環境では避けるべきなので、ここでコマンドで設定する方法を説明します。「winrm quickconfig」コマンドでサービスを起動してから、「winrm set」コマンドで信頼ホスト(TrustedHost)を追加する内容です。コマンドにある「x.x.x.x」は、WindowsインスタンスのパブリックIPアドレスです。

C:\> winrm quickconfig
WinRM はこのコンピューター上で要求を受信するように設定されていません。
次の変更を行う必要があります:

WinRM サービスを開始します。
WinRM サービスの種類を遅延自動開始に設定します。

変更しますか [y/n]? y
WinRM サービスの種類を正しく変更できました。
WinRM サービスが開始されました。
(中略)

C:\> winrm set winrm/config/client @{TrustedHosts="x.x.x.x"}
Client
    NetworkDelayms = 5000
    URLPrefix = wsman
    AllowUnencrypted = false
    Auth
        Basic = true
        Digest = true
        Kerberos = true
        Negotiate = true
        Certificate = true
        CredSSP = false
    DefaultPorts
        HTTP = 5985
        HTTPS = 5986
    TrustedHosts = x.x.x.x

接続してみる

以下のコマンドでリモート接続します。

C:\>winrs -u:Administrator -r:http://x.x.x.x:5985 cmd
'http://x.x.x.x:5985' に接続するための 'Administrator' のパスワードを入力してください:
Microsoft Windows [Version 10.0.20348.1668]
(c) Microsoft Corporation. All rights reserved.

C:\Users\Administrator>hostname
hostname
EC2AMAZ-VT3DD7Q

このように、コマンドを実行できるようになります。またPowershellも起動できcmdletを実行できます。

2. Powershell Remoting over WinRM

Powershell Remotingには、2つの方式があります。1つはWinRMベースでもう1つはSSHベースです。

WinRMベースのPowershell Remotingは、Windows OSからの接続しかサポートしません(WinRMがWindows OS上にしか存在しないため)。一方、SSHベースのPowershell Remotingはクロスプラットフォームであり、WindowsからLinux、LinuxからWindowsなどをサポートしています。しかし、SSHベースはWindows Powershellをサポートしておらず、Powershell(つまりPowershell Core)を動作要件としているため、サーバ側にのPowershellのインストールが必要です(名前がややこしいですが、Windows PoweshellとPowershellは別物です)。

WinRMベースのPowershell Remotingは、前述のWinRMの仕組みをそのまま流用しているため、サーバ側・クライアント側とも同様に事前設定が必要です。また、EC2側のポート開放(5985もしくは5986)も忘れずにしておきましょう。接続する際に、winrsコマンドの代わりに、Powershellで「Enter-PSSession」を利用します。

PS C:\WINDOWS\system32> Enter-PSSession -ComputerName x.x.x.x -Credential Administrator
[x.x.x.x]: PS C:\Users\Administrator\Documents>
[x.x.x.x]: PS C:\Users\Administrator\Documents> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.20348.1366
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.20348.1366
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

ちなみにHTTPSで接続する場合は以下のコマンドを利用します。

$ssloption = New-PsSessionOption –SkipCACheck -SkipCNCheck
Enter-PSSession -ComputerName x.x.x.x -Credential Administrator -UseSSL -SessionOption $ssloption

3. SSH

最新のWindowsサーバのリモートCLI管理は、SSHが最も簡単な方法です。Windows Server 2019以降、またWindows 10以降のWindows OSは、標準でOpenSSHをサポートしています。デフォルトでSSHサーバがインストールされているわけではありませんが、コマンド1つでインストールと構成ができるので複雑な設定は要りません。

まずは念のためOpenSSHのクライアント、サーバのインストール状況を確認します。

PS C:\Users\Administrator> Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'


Name  : OpenSSH.Client~~~~0.0.1.0
State : Installed

Name  : OpenSSH.Server~~~~0.0.1.0
State : NotPresent

OpenSSHのサーバがインストールされていないので、インストールします。

PS C:\Users\Administrator> Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0


Path          :
Online        : True
RestartNeeded : False

sshdサービスを起動し、自動起動に設定します。

PS C:\Users\Administrator> Start-Service sshd
PS C:\Users\Administrator> Set-Service -Name sshd -StartupType 'Automatic'

以上でサーバ側の設定は完了です。AWS上でSSHの22番ポートを開放すれば、クライアントからSSHで接続できるようになるはずです。

4. Powershell Remoting over SSH

SSHベースのPowershell Remotingは、クライアント側もサーバ側もWindows Powershellではなく、Powershell 6.0(=Powershell Core)以降のバージョンを必要とします。Server Coreで最新のPowershellをインストールするには、MSIパッケージを利用すると良いです。

PS C:\Users\Administrator> $URI="https://github.com/PowerShell/PowerShell/releases/download/v7.3.4/PowerShell-7.3.4-win-x64.msi"
PS C:\Users\Administrator> $File="PowerShell-7.3.4-win-x64.msi"
PS C:\Users\Administrator> Invoke-WebRequest -URI $URI -OutFile $File -UseBasicParsing

PS C:\Users\Administrator> start .\PowerShell-7.3.4-win-x64.msi

また、SSHベースのPowershell RemotingはSSHを前提としているので、先述の手順でOpenSSHサーバをインストールしておきます。インストールしたあと、sshd_configファイルを編集して、SSHのSubsystemを設定しておきます。

PS C:\Program Files\PowerShell\7> notepad $env:ProgramData\ssh\sshd_config

こちらの公式手順に従って、「Subsystem powershell c:/progra~1/powershell/7/pwsh.exe -sshs -nologo」を追記します。

設定ファイルを保存して、sshdを再起動します。

PS C:\Program Files\PowerShell\7> Restart-Service sshd

サーバ側の設定は以上で完了です。では、クライアントから接続してみます。

PS C:\Program Files\PowerShell\7> Enter-PSSession -HostName x.x.x.x -UserName Administrator
Administrator@x.x.x.x's password:
[Administrator@x.x.x.x]: PS C:\Users\Administrator\Documents>
[Administrator@x.x.x.x]: PS C:\Users\Administrator\Documents> Get-ComputerInfo | Select-Object OsName,WindowsInstallationType

OsName                                   WindowsInstallationType
------                                   -----------------------
Microsoft Windows Server 2022 Datacenter Server Core

ここで注意してほしいのは、Enter-PSSessionコマンドはover WinRMとover SSHの両方をサポートしており、パラメータでどちらを使うかが決まっています。例えば下記2つのコマンドについて、前者がover WinRMで後者がover SSHとなります。

Enter-PSSession -ComputerName x.x.x.x -Credential Administrator
Enter-PSSession -HostName x.x.x.x -UserName Administrator

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top