PowerShell Core 6.0の正式リリースに伴い、本エントリの内容を新しいバージョンでやり直しました。
こちらのエントリを参照してください。
blog.shibata.tech
PowerShell on Linux(Mac)が公開された際の新機能の一つにSSHによるPSRemoting(PowerShell Remoting over SSH)があります。
本エントリではこの機能を試してみます。
PowerShell Remoting over SSHとは
ドキュメントでの表記がPowerShell Remoting over SSH
、PowerShell Remoting Protocol(PSRP) over SSH
、PSRP over OpenSSH
等と若干揺れているのですが本エントリではPowerShell Remoting over SSH
で統一しておきます。
従来のPowerShell Remoting Protocol(PSRP)では通信の下回りにHTTP/HTTPSを使いますが、PowerShell Remoting over SSH
では名前の通りSSHを使った通信を行います。
基本的な仕組みとしては、
- クライアント側はpowershell(.exe)がリモートセッション生成時にssh(.exe)を呼び出し、powershell(.exe)→ssh(.exe)のプロセス間通信を経由してサーバーへの通信を行う。
- サーバー側はSSHdのサブシステムにPowerShellを登録。
クライアントからの接続があった場合はsshd(.exe)→powershell(.exe)とリモートシェルが実行される。
となっています。
仕様が公開されれいないため、ソースを読んだ限りでですが、PowerShell Remoting over SSHの仕組みはJobやPowerShell Directと同類でPSRPは(たぶん)使用しておらずWinRMにも依存していません。
このため、あくまでも私見ですが、PSRP over SSHという表記は正確でないと思われます。
このあたりはもう少し時間が経てば公式な情報も増えてくるかと思います。
PowerShell Remoting over SSHを試す
手順はGitHubDocsで公開されているのでこの手順をベースに行います。
https://github.com/PowerShell/PowerShell/tree/master/demos/SSHRemoting
試験環境
試験環境はVirtualBox上でWindows Server 2012 R2とCentOS 7.2.1511を使い双方向で通信させてみます。
これらのOSにした理由は単純に私が使い慣れているだけです。
他のOSでも細かい部分に違いはあるでしょうが基本的には同じ流れになると思います。
その他細かい条件は以下。
項目 |
Windows Server 2012 R2 |
CentOS 7.2.1511 |
基本設定 |
インストール直後の状態+最新のWindows Updateを実施 |
bento/centos7.2のBoxにyum updateを実施 |
IP |
192.168.33.210 |
192.168.33.209 |
ユーザー |
vagrant, administrator |
vagrant, root |
Windows → CentOSへの通信(パスワード認証)
最初にWindowsをクライアント、CentOSをサーバーにした場合の接続を試します。
CentOSにPowerShellをインストールします。
sudo yum install https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.9/powershell-6.0.0_alpha.91.el7.centos.x86_64.rpm -y
SSHdの設定変更を行います。
/etc/ssh/sshd_config
に次の設定を追加します。
Subsystem powershell powershell -sshs -NoLogo -NoProfile
追加例)
# /etc/ssh/sshd_config
# override default of no subsystems
Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem powershell powershell -sshs -NoLogo -NoProfile
また、必要に応じてパスワード認証、鍵認証の可否を設定します。
今回は試験環境のデフォルト設定のままとしました。
# Boxのデフォルト設定
PasswordAuthentication yes
#RSAAuthentication yes
#PubkeyAuthentication yes
設定変更後はSSHdを再起動します。
sudo systemctl restart sshd.service
これでCentOS側の設定は完了です。
次にWindows側の設定をします。
標準でインストールされているPowerShell 4.0ではPowerShell Remoting over SSHできませんので、こちらにもPowerShell Coreをインストールします。
Invoke-WebRequest -Uri "https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.9/PowerShell_6.0.0.9-alpha.9-win81-x64.msi" -OutFile "PowerShell_6.0.0.9-alpha.9-win81-x64.msi"
Start-Process -FilePath msiexec.exe -ArgumentList @("/i", "$($pwd.Path)\PowerShell_6.0.0.9-alpha.9-win81-x64.msi", "/passive") -Wait -PassThru
次にSSHをインストールします。
Zipの解凍をしたいので先ほどインストールたPowerShell Coreから以下の手順でインストールします。
Invoke-WebRequest -Uri "https://github.com/PowerShell/Win32-OpenSSH/releases/download/5_30_2016/OpenSSH-Win64.zip" -OutFile "OpenSSH-Win64.zip"
Expand-Archive -Path ".\OpenSSH-Win64.zip" -DestinationPath "C:\"
[Environment]::SetEnvironmentVariable('PATH', [Environment]::GetEnvironmentVariable('PATH') + ';C:\OpenSSH-Win64')
インストール先はC:\OpenSSH-Win64
としましたが、こちらについては必要に応じて変更しても構いません。
また、PowerShell Remoting over SSHではssh.exe
に対してPATHが通っていること(正確にはssh.exe
だけでコマンド呼び出しができること)が必須であるためPATHは必ず通す様にしてください。
これで準備が整いましたので実際に試してみます。
まずはNew-PSSession
でPSセッションを作成します。
-HostName
(-ComputerName
ではない)、-UserName
パラメーターを指定するとPowerShell Remoting over SSHで通信することになります。
$Session = New-PSSession -HostName 192.168.33.209 -UserName vagrant
実行すると以下の様にssh.exe
を使ってサーバーに接続する際のあれやこれやを聞かれるので適切な情報を入力していきます。
PS C:\Users\Administrator> $Session = New-PSSession -HostName 192.168.33.209 -UserName vagrant
The authenticity of host '192.168.33.209 (192.168.33.209)' can't be established.
ECDSA key fingerprint is SHA256:*******************************************.
Are you sure you want to continue connecting (yes/no)?
Please type 'yes' or 'no':
vagrant@192.168.33.209's password:
入力後、エラーが出なければ成功です。
$Session
の中身を確認すると以下の様になり、名前がSSHになっていることがわかります。
このセッションがssh.exe
と紐づいています。
PS C:\Users\Administrator> $Session
Id Name ComputerName ComputerType State Configuration
Name
-- ---- ------------ ------------ ----- -------------
1 SSH1 192.168.33.209 RemoteMachine Opened DefaultShell
この$session
を使いEnter-PSSession
してリモート接続します。
Enter-PSSession -Session $Session
実行結果は以下の様になり、CentOSにリモート接続できました。
PS C:\Users\Administrator> Enter-PSSession -Session $Session
[192.168.33.209]: PS /home/vagrant> cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[192.168.33.209]: PS /home/vagrant>
ちなみに既知の不具合としてリモートだとClear-Host
が使えません。
これはそのうち直ると思います。
[192.168.33.209]: PS /home/vagrant> Clear-Host
TERM environment variable not set.
とりあえずエラーメッセージの通りに
$env:TERM="vt100"
等とTERM
環境変数を適当に設定しておけば対処は可能です。
最後にRemove-PSSession
してセッション情報を削除すると紐づいていたssh.exe
も終了します。
Remove-PSSession -Session $Session
Get-PSSession | Remove-PSSession
Windows → CentOSへの通信(鍵認証)
鍵認証で通信する場合、基本的にSSHの鍵認証の方法と同一です。
先ずはWindows側でssh-keygen.exe
で鍵を作ります。
鍵の種類やパスフレーズの有無は適当にしてください。
以下の実行例ではRSA2 4096Byte、パスフレーズ有りにしています。
PS C:\> cd C:\OpenSSH-Win64\
PS C:\OpenSSH-Win64> .\ssh-keygen.exe -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\Administrator/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): ********
Enter same passphrase again: ********
Your identification has been saved in C:\Users\Administrator/.ssh/id_rsa.
Your public key has been saved in C:\Users\Administrator/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:******************************************* Administrator@WIN-7JINTK1PS1K
The key's randomart image is:
+---[RSA 4096]----+
| |
| |
| |
| |
| |
| |
| |
| |
| |
+----[SHA256]-----+
あとは作った公開鍵(id_rsa.pub
)をCentOS側に転送し~/.ssh/authorized_keys
に追加するだけです。
以下の例では/vagrant/id_rsa.pub
に鍵を転送しています。
cat /vagrant/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
これで鍵認証の準備は完了です。
鍵認証で接続する場合はNew-PSSession
の-KeyPath
パラメーターを使用します。
実行例は以下
PS C:\> $Session = New-PSSession -HostName 192.168.33.209 -UserName vagrant -KeyPath ~\.ssh\id_rsa
Enter passphrase for key 'C:\Users\Administrator\.ssh/id_rsa': ********
PS C:\> $Session
Id Name ComputerName ComputerType State Configuration
Name
-- ---- ------------ ------------ ----- -------------
1 SSH1 192.168.33.209 RemoteMachine Opened DefaultShell
セッションが生成された後はパスワード認証の場合と同様です。
CentOS → Windowsへの通信(パスワード認証)
最後に、あまり需要があるとは思いませんが、CentOSをクライアント、Windowsをサーバーにした場合の接続を試します。
面倒なのでパスワード認証のみとします。
まずはWindows上でSSHdを動作させます。
基本的にはGitHub上のインストール手順に従うだけなので問題ないかと思います。
cd C:\OpenSSH-Win64\
.\install-sshd.ps1
.\ssh-keygen.exe -A
New-NetFirewallRule -Protocol TCP -LocalPort 22 -Direction Inbound -Action Allow -DisplayName SSH
.\install-sshlsa.ps1
Restart-Computer
sshd_config
の設定はCentOSの場合と同様でサブシステムにPowerShell(Coreの方)を登録します。
Subsystem powershell C:/Program Files/PowerShell/6.0.0.9/powershell.exe -sshs -NoLogo -NoProfile
追加例)
# C:\OpenSSH-Win64\sshd_config
# override default of no subsystems
Subsystem sftp C:/Program Files/OpenSSH/sftp-server.exe
Subsystem powershell C:/Program Files/PowerShell/6.0.0.9/powershell.exe -sshs -NoLogo -NoProfile
設定後はサービスを再起動します。
Restart-Service sshd
これで準備は完了です。
CentOS側からWindowsへ接続してみます。
PS /home/vagrant> $Session = New-PSSession -HostName 192.168.33.210 -UserName administrator
The authenticity of host '192.168.33.210 (192.168.33.210)' can't be established.
ECDSA key fingerprint is ***********************************************.
Are you sure you want to continue connecting (yes/no)? yes
administrator@192.168.33.210's password: ********
セッション情報はこんな感じです。
PS /home/vagrant> $Session
Id Name ComputerName ComputerType State ConfigurationName Availability
-- ---- ------------ ------------ ----- ----------------- ------------
1 SSH1 192.168.33.210 RemoteMachine Opened DefaultShell Available
Enter-PSSession
でWindowsへ接続できます。
PS /home/vagrant> Enter-PSSession -Session $Session
[192.168.33.210]: PS C:\Users\Administrator\Documents>
ここでWindows側でPowerShell Coreが実行されていのですが、現時点ではまだ、PowerShell Core→PowerShell 4.0(Desktop)とネストしてPowerShellを対話的に実行できない様で、実際にやってみるとハングしてしまいます。
ただし、powershell.exe -Command {ほげ}
の様にコマンド実行であればネストして実行可能ですので、以下の例の様にPowerShell Coreにないコマンドレット(Get-NetFirewallRule
)を実行することもできます。
[192.168.33.210]: PS C:\> [System.Text.Encoding]::RegisterProvider([System.Text.CodePagesEncodingProvider]::Instance)
[192.168.33.210]: PS C:\> $OutputEncoding = [System.Text.Encoding]::GetEncoding(932)
[192.168.33.210]: PS C:\> powershell -Command { Get-NetFirewallRule -DisplayName *ssh* }
Name : {b467a636-88e4-4478-a408-e43a87356821}
ID : {b467a636-88e4-4478-a408-e43a87356821}
Group :
Platform : {}
LSM : False
Profile : Any
Caption :
Description :
ElementName : SSH
InstanceID : {b467a636-88e4-4478-a408-e43a87356821}
CommonName :
PolicyKeywords :
Enabled : 1
PolicyDecisionStrategy : 2
PolicyRoles :
ConditionListType : 3
CreationClassName : MSFT|FW|FirewallRule|{b467a636-88e4-4478-a408-e43a87356821}
ExecutionStrategy : 2
Mandatory :
PolicyRuleName :
Priority :
RuleUsage :
SequencedActions : 3
SystemCreationClassName :
SystemName :
Action : 2
Direction : 1
DisplayGroup :
DisplayName : SSH
EdgeTraversalPolicy : 0
EnforcementStatus : {0}
LocalOnlyMapping : False
LooseSourceMapping : False
Owner :
Platforms : {}
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : 1
PrimaryStatus : 1
Profiles : 0
RuleGroup :
Status : 規則は、ストアから正常に解析されました。
StatusCode : 65536
PSComputerName :
最後に
とりあえずこんな感じです。
WindowsからLinuxへのPSRemoting、なかなか胸が熱くなります。
実はWindowsからLinuxへPSRPを使用した接続も可能なのですが、まだバギーな部分が多い様で、このあたりについては別の機会にエントリを書こうと思います。
【2016/09/16追記】
続き書きました。
stknohg.hatenablog.jp
【2017/08/15追記】
Windows 10 Creators Updateでも使える様になっていたので別エントリを起こしました。
blog.shibata.tech