クラウド上の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