坑边闲话:笔者使用 SSH 已经有相当长时间了,只是笔者一直误以为 SSH 仅支持 Unix 系统。偶然发现,从 Windows Server 2019 和 Windows 10 1809 开始,微软将 OpenSSH 集成到了操作系统中,这意味着我们可以直接在 Windows 上使用原生的 SSH 功能了!虽然体验没有 Unix 系那么完美,但是在一些特殊场景还是具有很大的作用。本文将带你深入了解 Windows 上的 OpenSSH 服务器配置,无论你是想远程管理服务器,还是想搭建一个安全的文件传输环境,这篇文章都能帮到你。

Windows 的 OpenSSH 并不是开箱即用,甚至也不能一行命令就启用。这说明 SSH 连接在 Windows 场景下是二等公民。微软的官方文档是最终权威教程,本文只做简单介绍。

1. 什么是 OpenSSH?·

OpenSSH 是一个开源的 SSH 协议实现,它提供了加密的网络通信服务。简单来说,通过 SSH 你可以:

  • 远程登录到计算机并执行命令
  • 安全地传输文件(通过 SCP 或 SFTP)
  • 建立加密的网络隧道

在 Windows 中集成 OpenSSH 后,你可以像在 Linux 上一样,通过命令行远程管理 Windows 服务器,而不需要依赖图形界面的远程桌面。

2. 配置文件位置·

2.1 服务器端配置·

OpenSSH 服务器的配置文件位于:

1
%programdata%\ssh\sshd_config

通常这个路径展开后是 C:\ProgramData\ssh\sshd_config.

如果你想使用其他位置的配置文件,可以在启动 sshd.exe 时使用 -f 参数指定:

1
sshd.exe -f "C:\自定义路径\my_sshd_config"

如果配置文件不存在,SSH 服务在首次启动时会自动生成一个包含默认配置的文件。

sshd 配置文件

Windows 的 sshd 配置和 Linux 几乎没有区别。一般我们只需要关心:

  • Port 22,
  • PubkeyAuthentication yes,
  • PasswordAuthentication no

等选项即可,后面会继续介绍其他 sshd_config 项目。

2.2 客户端配置·

温馨提示

如果你已经在使用 SSH 客户端一阵子了,那么本小节并不会引入新的知识。直接略过即可。

客户端连接其他 SSH 服务器时,OpenSSH 客户端会按以下顺序读取配置:

  1. 通过 ssh.exe -F 参数指定的配置文件
  2. 用户配置文件:%userprofile%\.ssh\config, 通常是 C:\Users\USERNAME\.ssh\config.
  3. 系统全局配置:%programdata%\ssh\ssh_config

3. 配置服务器的默认 Shell·

3.1 什么是默认 Shell?·

当用户通过 SSH 连接到你的 Windows 服务器时,系统会启动一个命令行环境,这就是 Shell.

Windows 默认使用的是传统的命令提示符 cmd.exe,但可以更换为更现代化、更强大的 PowerShell.

3.2 如何设置默认 Shell·

首先,确认 OpenSSH 的安装目录在系统路径中。默认安装路径是:

1
%systemdrive%\Windows\System32\openssh

你可以通过以下命令查看当前的 PATH 设置:

在命令提示符中:

1
path

在 PowerShell 中:

1
$env:path

如果没有安装,则可进入系统设置可选功能搜索并安装 OpenSSH 服务器

图 1. 搜索并安装可选的 OpenSSH 组件并安装。

3.3 修改默认 shell 为 PowerShell·

要将默认 Shell 改为 PowerShell,需要修改注册表。以管理员权限打开 PowerShell,运行以下命令:

1
2
3
4
5
6
# 以管理身份执行
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" `
-Name DefaultShell `
-Value "C:/Program Files/PowerShell/7/pwsh.exe" `
-PropertyType String `
-Force

注意:在使用之前应该先下载安装现代版 PowerShell, 如果非要使用系统默认的老旧版本 PowerShell,可以替换为下列命令:

1
2
3
4
5
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH"
-Name "DefaultShell" `
-Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
-PropertyType String
-Force

这样,用户通过 SSH 连接后就会直接进入 PowerShell 环境了。

注意:这个设置只影响 SSH 服务器端,不影响本地的 SSH 客户端行为。

3.4 核心配置选项详解·

配置 OpenSSH 服务器时,需要编辑 sshd_config 文件。每次修改配置后,都需要重启 SSH 服务才能生效:

1
Restart-Service sshd

4. 用户和组访问控制·

OpenSSH 提供了四个指令来控制哪些用户可以或不可以连接:

  • AllowUsers - 允许特定用户连接
  • DenyUsers - 拒绝特定用户连接
  • AllowGroups - 允许特定组的成员连接
  • DenyGroups - 拒绝特定组的成员连接

处理顺序很重要:系统会按照 DenyUsersAllowUsersDenyGroupsAllowGroups 的顺序处理这些规则。

4.1 格式要求·

  1. 所有账户名必须使用小写
  2. 对于域用户或组,使用格式:user?domain*
  3. 工作组用户使用本地账户名(不含域名部分)
  4. 域用户和组会解析为 域简称\用户名 格式(例如:contoso\admin

4.1.1 实例一:混合策略·

1
2
3
DenyUsers contoso\[email protected]
DenyUsers contoso\*
AllowGroups contoso\sshusers contoso\serveroperators

这个配置的含义是:

  • 拒绝来自 IP 地址 192.168.2.23 的 contoso\admin 用户
  • 拒绝 contoso 域的所有用户
  • 但允许 contoso\sshusers 和 contoso\serveroperators 组的成员

4.1.2 实例二:简单白名单·

1
2
AllowUsers [email protected]
AllowGroups sshusers

这个配置只允许:

  • 来自 192.168.2.23 的本地用户 localuser
  • sshusers 组的所有成员

4.2 身份验证·

在 Windows 的 OpenSSH 中,只支持两种身份验证方法:

  • password - 密码验证
  • publickey - 公钥验证

可以在配置文件中这样设置:

1
AuthenticationMethods publickey password

重要提示:目前不支持通过 Microsoft Entra(Azure AD)账户进行身份验证。

4.3 公钥文件位置·

公钥验证是比密码更安全的方式。OpenSSH 会在以下位置查找授权的公钥:

普通用户:

1
.ssh/authorized_keys

如果不指定绝对路径,OpenSSH 会在用户的主目录下查找,例如 C:\Users\USERNAME\.ssh\authorized_keys

管理员用户:

对于属于管理员组的用户,系统会使用:

1
%programdata%/ssh/administrators_authorized_keys

通常是 C:\ProgramData\ssh\administrators_authorized_keys。由于绝大多数人的普通账户属于管理员组,因此只需修改本文件即可。

4.4 重要的权限设置·

administrators_authorized_keys 文件的权限设置必须正确,否则会导致验证失败。正确的权限设置是:

  • 只允许 NT Authority\SYSTEM 账户和 BUILTIN\Administrators 组有权限
  • NT Authority\SYSTEM 必须有完全控制权限

可以用以下命令设置正确的权限:

1
icacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"

4.5 GSSAPI/Kerberos 认证·

从 Windows Server 2022、Windows 11 和 Windows 10(2021年5月更新)开始,OpenSSH 支持 GSSAPI(基于 Kerberos)认证。

在服务器配置文件中启用:

1
GSSAPIAuthentication yes

在客户端使用时,需要添加 -K 参数并指定主机名:

1
ssh -K SERVER01.contoso.com

或者在客户端配置文件(%userprofile%\.ssh\config)中添加:

1
2
3
Host SERVER01.contoso.com
GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes

4.6 主机密钥·

SSH 服务器需要密钥来标识自己。默认配置中包含多种密钥类型:

1
2
3
4
#HostKey __PROGRAMDATA__/ssh/ssh_host_rsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_dsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ecdsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ed25519_key

如果这些密钥文件不存在,SSH 服务会在启动时自动生成它们。你通常不需要手动干预这个过程。

4.7 日志配置·

如果需要基于文件的日志记录,可以设置:

1
SyslogFacility LOCAL0

日志文件会保存在:

1
%programdata%\ssh\logs

如果使用其他值(包括默认的 AUTH),日志会通过 ETW(Windows 事件跟踪)记录。你可以在 Windows 事件查看器中查看这些日志。

4.8 Chroot 目录(隔离环境)·

从 OpenSSH 7.7.0.0 版本开始,Windows 支持 ChrootDirectory 配置,但仅适用于 SFTP 会话。

这个功能可以将用户限制在特定目录中,常用于安全的文件传输服务器。配置示例:

1
2
3
Match Group sftpusers
ChrootDirectory C:\sftp\%u
ForceCommand internal-sftp

这会将 sftpusers 组的成员限制在 C:\sftp\用户名 目录中,并只允许他们使用 SFTP。

注意:这个限制对 cmd.exe 远程会话不起作用。

4.8 条件匹配规则·

Match 指令允许你根据条件应用不同的配置。常见的匹配条件包括用户、组、主机等。

示例:为特定组配置特殊规则

1
2
3
4
5
6
7
Match Group developers
AllowTcpForwarding yes
X11Forwarding no

Match Group restricted
AllowTcpForwarding no
ForceCommand internal-sftp

记住:用户和组名称应该使用小写。

4.9 管理员登录·

Windows 中没有像 Linux 那样的 root 用户概念。如果你想阻止管理员通过 SSH 登录,可以使用:

1
DenyGroups Administrators

5. 放行 ssh 入站流量·

默认情况下,即使你开启了 SSHD,Windows Defender 防火墙依然会阻止 SSHD 所在端口的入站流量。执行下列代码可以创建防火墙放行规则。

1
2
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH SSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -Program "C:\Windows\System32\OpenSSH\sshd.exe"
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH SSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -Program "C:\Program Files\OpenSSH\sshd.exe"

6. Windows 特有的限制·

需要注意的是,Windows 版本的 OpenSSH 并不支持所有标准的 OpenSSH 配置选项。以下是一些不可用的选项:

  • AllowStreamLocalForwarding - 本地流转发
  • AuthorizedKeysCommand - 授权密钥命令
  • KerberosAuthentication - Kerberos 认证(注意这与 GSSAPI 不同)
  • PermitTunnel - 隧道许可
  • X11Forwarding - X11 图形转发
  • 以及其他一些高级选项

这些限制主要是因为 Windows 和 Linux 系统架构的差异。对于大多数日常使用场景,现有的功能已经足够。

7. 实战:一个完整的配置示例·

下面是一个适合小型企业环境的完整配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 基本设置
Port 22
Protocol 2

# 主机密钥
HostKey __PROGRAMDATA__/ssh/ssh_host_rsa_key
HostKey __PROGRAMDATA__/ssh/ssh_host_ed25519_key

# 日志
SyslogFacility LOCAL0
LogLevel INFO

# 身份验证
AuthenticationMethods publickey password
PubkeyAuthentication yes
PasswordAuthentication yes
PermitEmptyPasswords no

# 公钥文件位置
AuthorizedKeysFile .ssh/authorized_keys

# 禁止管理员使用密码登录,只允许公钥
Match Group Administrators
AuthenticationMethods publickey

# 允许的用户组
AllowGroups contoso\ssh-users contoso\developers

# 拒绝特定用户
DenyUsers contoso\testuser

# SFTP 专用用户配置
Match Group sftp-only
ChrootDirectory C:\sftp\%u
ForceCommand internal-sftp
AllowTcpForwarding no

8. 常见问题排查·

问题 1:配置修改后不生效·

原因:忘记重启 SSH 服务。

解决方法

1
Restart-Service sshd

问题 2:管理员无法使用公钥登录·

原因administrators_authorized_keys 文件权限不正确。

解决方法:运行权限修复命令

1
icacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"

问题 3:域用户无法登录·

原因:用户名格式不正确,或者没有正确配置允许规则。

解决方法

  • 确保使用 domain\username 格式(全部小写)
  • 检查 AllowUsersAllowGroups 配置
  • 确认处理顺序(Deny 规则优先于 Allow 规则)

问题 4:找不到配置文件·

原因:配置文件路径不正确,或者文件被意外删除。

解决方法:重启 SSH 服务,它会自动生成默认配置文件

1
Restart-Service sshd

8. 安全最佳实践·

  1. 优先使用公钥认证:公钥认证比密码更安全,应该作为首选方式。
  2. 限制允许登录的用户:不要让所有用户都能通过 SSH 访问,使用 AllowUsersAllowGroups 创建白名单。
  3. 禁用密码认证(可选):如果所有用户都配置了公钥,可以完全禁用密码验证:
    1
    PasswordAuthentication no
  4. 更改默认端口(可选):虽然这是"隐蔽式安全",但将 SSH 端口从 22 改为其他端口可以减少自动化扫描:
    1
    Port 2222
  5. 启用详细日志:在调试问题或监控访问时很有用:
    1
    LogLevel VERBOSE
  6. 定期审查授权密钥:定期检查 authorized_keys 文件,删除不再需要的公钥。
  7. 限制管理员访问:考虑只允许管理员使用公钥,并可能要求来自特定 IP:
    1
    2
    3
    Match Group Administrators
    AuthenticationMethods publickey
    AllowUsers *@192.168.1.*

总结·

Windows 集成 OpenSSH 是微软拥抱开源社区的重要一步,它让 Windows 服务器的管理变得更加灵活和高效。虽然 Windows 版本的 OpenSSH 在某些高级功能上还有限制,但对于绝大多数使用场景来说已经完全够用。现在,你可以开始在自己的 Windows 环境中配置和使用 SSH 了。

参考资源·