通过 SSH 进行 PowerShell 远程处理

概述

PowerShell 远程处理通常使用 WinRM 进行连接协商和数据传输。 SSH 现在可用于 Linux 和 Windows 平台,并允许进行真正的多平台 PowerShell 远程处理。

WinRM 为 PowerShell 远程会话提供可靠的托管模型。 基于 SSH 的远程处理目前不支持远程终结点配置和 Just Enough Administration (JEA)。

通过 SSH 远程管理,您可以在 Windows 和 Linux 计算机之间执行基本的 PowerShell 会话远程管理。 SSH 远程处理会在目标计算机上创建一个 PowerShell 托管进程作为 SSH 子系统。 最终,我们将实现类似于 WinRM 的常规托管模型,以支持终结点配置和 JEA。

New-PSSessionEnter-PSSessionInvoke-Command cmdlet 现在已有一个新参数集,以支持此新的远程处理连接。

[-HostName <string>]  [-UserName <string>]  [-KeyFilePath <string>]

若要创建远程会话,请使用 HostName 参数指定目标计算机,并使用 UserName 提供用户名。 以交互方式运行 cmdlet 时,系统会提示输入密码。 还可以将私钥文件与 KeyFilePath 参数配合使用 SSH 密钥身份验证。 创建用于 SSH 身份验证的密钥因平台而异。

常规设置信息

PowerShell 6 或更高版本,必须在所有计算机上安装 SSH。 安装 SSH 客户端 (ssh.exe) 和服务器 (sshd.exe),以便可以远程访问和传出计算机。 OpenSSH for Windows 现已在 Windows 10 内部版本 1809 和 Windows Server 2019 中提供。 有关详细信息,请参阅 使用 OpenSSH 管理 Windows。 对于 Linux,请安装适用于平台的 SSH(包括 sshd 服务器)。 为了启用 SSH 远程处理功能,您还需要从 GitHub 安装 PowerShell。 SSH 服务器必须配置为创建 SSH 子系统,以在远程计算机上托管 PowerShell 进程。 而且,必须启用 基于密码基于密钥的 身份验证。

在 Windows 计算机上安装 SSH 服务

  1. 安装最新版本的 PowerShell。 有关详细信息,请参阅 在 Windows 上安装 PowerShell

    可以通过列出 New-PSSession 参数集来确认 PowerShell 是否支持 SSH 远程处理。 你会注意到有参数集名称以 SSH 开头。 这些参数集包括 SSH 参数。

    (Get-Command New-PSSession).ParameterSets.Name
    
    Name
    ----
    SSHHost
    SSHHostHashParam
    
  2. 安装最新的 Win32 OpenSSH。 有关安装说明,请参阅 OpenSSH 入门

    注释

    如果要将 PowerShell 设置为 OpenSSH 的默认 shell,请参阅 “为 OpenSSH 配置 Windows”。

  3. $Env:ProgramData\ssh中编辑sshd_config文件。

    确保已启用密码身份验证:

    PasswordAuthentication yes
    

    创建在远程计算机上托管 PowerShell 进程的 SSH 子系统:

    Subsystem powershell C:/progra~1/powershell/7/pwsh.exe -sshs -NoLogo
    

    注释

    从 PowerShell 7.4 开始,在 SSH 服务器模式下运行 PowerShell 时,不再需要使用 -NoLogo 参数。

    注释

    PowerShell 可执行文件的默认位置为 C:/progra~1/powershell/7/pwsh.exe。 位置可能因安装 PowerShell 的方式而异。

    对于包含空格的任何文件路径,必须使用 8.3 短名称。 OpenSSH for Windows 中有一个 bug,它阻止空格在子系统可执行文件路径中发挥作用。 有关详细信息,请参阅此 GitHub 问题

    Windows 中文件夹的 Program Files 8.3 短名称通常是 Progra~1。 但是,可以使用以下命令来确保:

    Get-CimInstance Win32_Directory -Filter 'Name="C:\\Program Files"' |
      Select-Object EightDotThreeFileName
    
    EightDotThreeFileName
    ---------------------
    C:\progra~1
    

    (可选)启用密钥身份验证:

    PubkeyAuthentication yes
    

    有关详细信息,请参阅 管理 OpenSSH 密钥

  4. 重启 sshd 服务。

    Restart-Service sshd
    
  5. 将 OpenSSH 的安装路径添加到 PATH 环境变量中。 例如,C:\Program Files\OpenSSH\。 此条目旨在使ssh.exe能够被找到。

在 Ubuntu Linux 计算机上安装 SSH 服务

  1. 安装最新版本的 PowerShell,请参阅在 Ubuntu 上安装 PowerShell

  2. 安装 Ubuntu OpenSSH 服务器

    sudo apt install openssh-client
    sudo apt install openssh-server
    
  3. 请在/etc/ssh的位置编辑sshd_config文件。

    确保已启用密码身份验证:

    PasswordAuthentication yes
    

    (可选)启用密钥身份验证:

    PubkeyAuthentication yes
    

    有关在 Ubuntu 上创建 SSH 密钥的详细信息,请参阅 ssh-keygen 的 manpage。

    添加 PowerShell 子系统条目:

    Subsystem powershell /usr/bin/pwsh -sshs -NoLogo
    

    注释

    PowerShell 可执行文件的默认位置为 /usr/bin/pwsh。 位置可能因安装 PowerShell 的方式而异。

    注释

    从 PowerShell 7.4 开始,在 SSH 服务器模式下运行 PowerShell 时,不再需要使用 -NoLogo 参数。

  4. 重启 ssh 服务。

    sudo systemctl restart sshd.service
    

在 macOS 计算机上安装 SSH 服务

  1. 安装最新版本的 PowerShell。 有关详细信息,请在 macOS 上安装 PowerShell

    按照以下步骤确保启用了 SSH 远程处理:

    1. 打开 System Settings
    2. 单击 General
    3. 单击 Sharing
    4. 检查 Remote Login 以设置 Remote Login: On
    5. 允许适当的用户访问。
  2. 请在/private/etc/ssh/sshd_config的位置编辑sshd_config文件。

    使用文本编辑器,例如 nano

    sudo nano /private/etc/ssh/sshd_config
    

    确保已启用密码身份验证:

    PasswordAuthentication yes
    

    添加 PowerShell 子系统条目:

    Subsystem powershell /usr/local/bin/pwsh -sshs -NoLogo
    

    注释

    PowerShell 可执行文件的默认位置为 /usr/local/bin/pwsh。 位置可能因安装 PowerShell 的方式而异。

    注释

    从 PowerShell 7.4 开始,在 SSH 服务器模式下运行 PowerShell 时,不再需要使用 -NoLogo 参数。

    (可选)启用密钥身份验证:

    PubkeyAuthentication yes
    
  3. 重启 sshd 服务。

    sudo launchctl stop com.openssh.sshd
    sudo launchctl start com.openssh.sshd
    

注释

在您升级操作系统时,您的 SSH 配置文件可能会被覆盖。 请确保在升级后检查配置文件。

身份验证

通过 SSH 进行 PowerShell 远程处理依赖于 SSH 客户端与 SSH 服务之间的身份验证交换,并且不实现任何身份验证方案本身。 结果是,任何配置的身份验证方案(包括多重身份验证)都由 SSH 处理,独立于 PowerShell。 例如,可以将 SSH 服务配置为要求公钥身份验证和一次性密码,以增加安全性。 多重身份验证的配置超出了本文档的范围。 请参阅有关 SSH 的文档,了解如何正确配置多重身份验证并在 PowerShell 外部验证它是否正常工作,然后再尝试将其与 PowerShell 远程处理配合使用。

注释

用户在远程会话中保留相同的权限。 这意味着,管理员可以访问高级的 shell 环境,而普通用户则无法访问。

PowerShell 远程操作示例

测试远程操作的最简单方法是在一台计算机上试用它。 在此示例中,我们创建了一个回到同一台 Linux 计算机的远程会话。 我们以交互方式使用 PowerShell cmdlet,因此我们看到来自 SSH 的提示,要求验证主计算机并提示输入密码。 你可以在 Windows 计算机上执行相同的操作,以确保远程连接正常工作。 然后,通过更改主机名在计算机之间进行远程连接。

Linux 到 Linux

$session = New-PSSession -HostName UbuntuVM1 -UserName TestUser
The authenticity of host 'UbuntuVM1 (9.129.17.107)' can't be established.
ECDSA key fingerprint is SHA256:2kCbnhT2dUE6WCGgVJ8Hyfu1z2wE4lifaJXLO7QJy0Y.
Are you sure you want to continue connecting (yes/no)?
TestUser@UbuntuVM1s password:
$session
 Id Name   ComputerName    ComputerType    State    ConfigurationName     Availability
 -- ----   ------------    ------------    -----    -----------------     ------------
  1 SSH1   UbuntuVM1       RemoteMachine   Opened   DefaultShell             Available
Enter-PSSession $session
[UbuntuVM1]: PS /home/TestUser> uname -a
Linux TestUser-UbuntuVM1 4.2.0-42-generic 49~16.04.1-Ubuntu SMP Wed Jun 29 20:22:11 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

[UbuntuVM1]: PS /home/TestUser> Exit-PSSession
Invoke-Command $session -ScriptBlock { Get-Process pwsh }
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName    PSComputerName
-------  ------    -----      -----     ------     --  -- -----------    --------------
      0       0        0         19       3.23  10635 635 pwsh           UbuntuVM1
      0       0        0         21       4.92  11033 017 pwsh           UbuntuVM1
      0       0        0         20       3.07  11076 076 pwsh           UbuntuVM1

Linux 到 Windows

Enter-PSSession -HostName WinVM1 -UserName PTestName
PTestName@WinVM1s password:
[WinVM1]: PS C:\Users\PTestName\Documents> cmd /c ver
Microsoft Windows [Version 10.0.10586]

Windows 到 Windows

C:\Users\PSUser\Documents>pwsh.exe
PowerShell
Copyright (c) Microsoft Corporation. All rights reserved.
$session = New-PSSession -HostName WinVM2 -UserName PSRemoteUser
The authenticity of host 'WinVM2 (10.13.37.3)' can't be established.
ECDSA key fingerprint is SHA256:kSU6slAROyQVMEynVIXAdxSiZpwDBigpAF/TXjjWjmw.
Are you sure you want to continue connecting (yes/no)?
Warning: Permanently added 'WinVM2,10.13.37.3' (ECDSA) to the list of known hosts.
PSRemoteUser@WinVM2's password:
$session
 Id Name            ComputerName    ComputerType    State         ConfigurationName     Availability
 -- ----            ------------    ------------    -----         -----------------     ------------
  1 SSH1            WinVM2          RemoteMachine   Opened        DefaultShell             Available
Enter-PSSession -Session $session
[WinVM2]: PS C:\Users\PSRemoteUser\Documents> $PSVersionTable

Name                           Value
----                           -----
PSEdition                      Core
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
SerializationVersion           1.1.0.1
BuildVersion                   3.0.0.0
CLRVersion
PSVersion                      6.0.0-alpha
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
GitCommitId                    v6.0.0-alpha.17


[WinVM2]: PS C:\Users\PSRemoteUser\Documents>

局限性

  • sudo 命令在与 Linux 计算机的远程会话中不起作用。

  • 通过 SSH 的 PSRemoting 不支持配置文件,并且无法访问 $PROFILE。 进入会话后,可以通过点溯源包含完整文件路径的配置文件来加载配置文件。 这与 SSH 配置文件无关。 可以将 SSH 服务器配置为使用 PowerShell 作为默认 shell,并通过 SSH 加载配置文件。 有关详细信息,请参阅 SSH 文档。

  • 在 PowerShell 7.1 之前,通过 SSH 进行远程处理不支持第二跃点远程会话。 此功能仅限于使用 WinRM 的会话。 PowerShell 7.1 允许 Enter-PSSessionEnter-PSHostProcess 在任何交互式远程会话中工作。

另请参阅