Remote SSH Access PowerShell

摘要:本文介绍如何实现通过 SSH 远程连接到 PowerShell。其使用场景主要在 Linux 环境下远程访问 Windows 下的 PowerShell,从而能够将 Windows 的相关操作和部署脚本自动化。

本文主要参考微软官方文档:PowerShell Remoting Over SSH,同时介绍在配置过程中遇到的问题。该文档十分详细,并且介绍了各种操作系统之间的配置,这里我们主要介绍 Windows 作为服务器,Linux 作为客户端的场景。

另外这篇文章Configure SSH-based PowerShell Core remoting between Windows and Linux也比较详细,可以对比参考。

安装 PowerShell Core for Windows

目前最新的 Windows 已经集成了 PowerShell,但是这里还是需要单独安装一份,因为这个 PowerShell 将会配置为 SSH 的子系统。而且新安装的 PowerShell 和内置的是独立。

单独安装的好处:

  1. 版本统一,我们可以使用当前 GitHub 最新的 PowerShell,并且在客户端和服务器端部署一致的版本。
  2. 配置简单,不需要知道内置的 PowerShell 的属性。

安装过程很简单,一般情况下我们字需要到 GitHubRelease 页面上下载 MSI 安装包 PowerShell-版本号-win-x64.msi,直接下一步就可以了。

默认安装完成后我们会在 C:\Program Files\PowerShell\6-preview 路径下看到 PowerShell 的相关文件。最后一层文件夹是版本号。

安装完成后,我们需要测试一下是否支持 SSH Remoting

1
Get-Command New-PSSession -syntax

预期的结果应该包含:

1
New-PSSession [-HostName] <string[]> [-Name <string[]>] [-UserName <string>] [-KeyFilePath <string>] [-SSHTransport] [<CommonParameters>]

安装 Win32 OpenSSH

通过 GitHubRelease 页面上下载 ZIP,解压到指定文件夹,一般为:C:\Program Files\OpenSSH

然后通过参考官方安装文档 Install Win32 OpenSSH 进行安装,这里使用命令行进行安装

执行安装 PowerShell 脚本

1
powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1

配置防火墙

1
2
3
4
# Windows 2012 above
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
# Other
netsh advfirewall firewall add rule name=sshd dir=in action=allow protocol=TCP localport=22

启动服务,并且配置自动启动

1
2
3
net start sshd
Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic

配置 sshd

这一步是最关键的,也是最容易报错的。

基础配置项

Windows 环境下,sshd 的配置文件和相关的证书日志,都会存放在 C:\ProgramData\ssh 下,这点需要注意,安装路径存放这一份默认的配置,这个只是为了恢复使用的。官方的安装手册的第7条有介绍:

To use existing customized sshd_config, you need to copy it from binary location to %programdata%\ssh\sshd_config (Note that %programdata% is a hidden directory).

使用 password authentication

1
PasswordAuthentication yes

使用 key authentication (可选)

1
PubkeyAuthentication yes

配置子系统

1
Subsystem powershell c:/program files/powershell/6.0.4/pwsh.exe -sshs -NoLogo -NoProfile

这里需要说明,如果遇到问题,可以是因为配置子系统的路径中有空格导致,这也是一个目前还是 OpenIssue。可以通过创建 symlink 来解决这个问题。

首先我们将原始 PowerShell 的安装路径创建一个 symlink,这里注意,如果在 PowerShell 中执行 mklink 需要加 cmd /c 因为这个执行不是 PowerShell 的,参考该回答

1
cmd /c mklink /D c:\pwsh "C:\Program Files\PowerShell\6-preview"

然后我们就用 symlink 来配置子系统,这样就排除了空格的问题。

1
Subsystem powershell c:\pwsh\pwsh.exe -sshs -NoLogo -NoProfile

https://docs.microsoft.com/en-us/powershell/scripting/core-powershell/ssh-remoting-in-powershell-core?view=powershell-6

https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH

重启服务

1
Restart-Service sshd

问题排查

我们一般通过开启调试日志的方式调试 sshd,官方有专门的 Troubleshooting 页面,一般我们开启调试配置。

删除原有的日志文件,在配置文件 sshd_config 增加如下条目

1
2
3
SyslogFacility LOCAL0
LogLevel to DEBUG
# (or DEBUG2/DEBUG3 for higher levels of logging)

然后重启

1
2
Stop-Service sshd
Start-Service sshd

这时候访问就会产生日志文件,写入 log 文件夹中。

Linux 客户端配置

本人使用 Fedora,其他的发行版基本是一样的。

首先在 Linux 上安装 PowerShell, 参考该文:Installing PowerShell Core on Linux

Ubuntu, Debian

1
2
sudo apt-get install -y powershell	
sudo apt-get install -y powershell-preview

CentOS, RedHat

1
2
sudo yum install -y powershell	
sudo yum install -y powershell-preview

OpenSUSE

1
2
sudo zypper install powershell	
sudo zypper install powershell-preview

Fedora

1
2
sudo dnf install -y powershell	
sudo dnf install -y powershell-preview

安装好后就可以使用 PowerShell,直接使用 pwsh 命令进入 PowerShell 的命令行窗口。

然后使用如下指令远程连接到服务器:

1
Enter-PSSession -HostName [IP or HostName] -UserName Administrator

当然按照官方文档所述,还可以定义 $session 变量,然后通过变量登陆。

1
2
3
$session = New-PSSession -HostName UbuntuVM1 -UserName TestUser
$session
Enter-PSSession $session

常见问题

subsystem request failed on channel 0

检查 sshd 的子系统的配置,有可能是空格问题,使用 symlink 配置。

sshd 日志:CreateProcessAsUser failed error:1314

“To resolve this problem, you’ll need to elevate the rights of the account calling CreateProcessAsUser with the “Replace a process level token” right. To do so, open the Control Panel / Administrative Tools / Local Security Policy and add the user account to the “Replace a process level token” right. (You may have to logout or even reboot to have this change take effect.)”

参考该文章解决: https://social.msdn.microsoft.com/Forums/vstudio/en-US/c905c900-cae1-4081-b0c9-00f10238e7ad/createprocessasuser-failed?forum=clr

主要就是在 Control Panel / Administrative Tools / Local Security Policy 找到 Replace a process level token 权限,然后将需要远程连接的用户的加入到这个权限中. 需要重启电脑.

enter description here

总结

通过这个配置,我们就可以针对 Windows 服务器进行 Devops,比如 GitLab 就支持执行 PowerShell 脚本,参考:Shells supported by GitLab Runner