在 Windows 10 上装 OpenSSH 服务听起来是一件小事但我发现周围不少人卡在很基础的环节要么装完自己本机都连不通要么管理员账户始终报 Permission denied要么使用密钥登录时被默认的授权文件路径坑得团团转。这篇文章把我实际安装、配置、排障的经验完整梳理出来从零开始讲清楚 Windows 10 上 OpenSSH 服务的安装方式、关键配置文件、密钥认证链路、防火墙策略以及常见故障排查思路适合需要远程管理 Windows 机器、想把这台工作电脑当成跳板机或者纯粹想在 Windows 环境里学习 SSH 工作原理的读者。1. 装之前先搞清楚的三件事很多教程上来就是一条命令装好、两条命令启动确实很快但容易漏掉后续使用时的关键前提。这里想先聊三个我自己的判断和踩坑心得。1.1 Windows 10 自带 OpenSSH 与第三方 SSH 服务怎么选Windows 10 从 1809 开始把 OpenSSH 客户端和服务器作为可选功能内置到系统里。也就是说不需要额外下载安装包直接在系统设置里添加即可长期维护跟 Windows Update 走干净省事基本不依赖第三方软件。那还有没有必要用 Bitvise SSH Server、FreeSSHd 这类第三方工具我的看法是绝大多数日常场景不需要。Windows 自带的 Win32-OpenSSH 服务虽然界面朴素但作为微软官方移植的 OpenSSH 实现兼容性有保障你从 Linux 带过来的那条ssh userhost习惯可以原封不动用上。第三方工具的优势在于图形化用户管理、虚拟账户映射、细致到单用户的权限控制这些功能适合企业复杂环境个人或小团队用不上反而要多维护一个软件。顺便说一句如果你平时同时管理 Linux 服务器可能会在搜索时看到 CentOS、麒麟等系统下通过 RPM 包或者源码升级 OpenSSH 的操作。在 Linux 上源码编译或替换 RPM 很常见但同样是 OpenSSHWindows 上没必要这么折腾。Windows 上的升级路径一般就是两个通过系统更新获取微软打包的版本或者从微软官方开源仓库下载 Win32-OpenSSH 的最新发布包做替换。这个后面会专门讲。1.2 默认端口、防火墙规则与安装后的服务形态Windows 自带 OpenSSH 服务安装后的服务名是sshd程序位置在C:\Windows\System32\OpenSSH\sshd.exe。默认监听 22 端口和 Linux 上没有任何区别。但很多人装完第一步就栽在防火墙上。虽然系统在安装 OpenSSH 服务时会自动创建名为OpenSSH-Server-In-TCP的入站规则但这条规则的默认生效范围是“专用网络”。如果你的电脑当前网络被系统标记为“公用网络”外网设备连接时就会被拦截。我自己测试时遇到过这种情况同一台机器内网 IP 怎么都连不上打开防火墙一看规则只对 Private 有效而当前网卡对应的是 Public 配置。所以装完服务后建议手动确认一下这条规则甚至直接给它指定允许的远程来源地址避免把端口暴露到不期望的网络里。1.3 明确你要用哪个账户登录Windows 的 OpenSSH 服务默认以SYSTEM账户运行这和 Linux 的sshd以 root 或专用用户运行有相似之处但登录用户的权限模型差别很大。一个重要事实Windows 上没有 root 这个概念SSH 登录后拿到的权限取决于你登录的 Windows 账户。如果你的账户属于本地管理员组Administrators那么你在默认配置下会被特殊对待尤其是 authorized_keys 文件的读取路径与普通用户完全不同。这一点不提前知道密钥登录很可能翻车后面我会专门拆开讲。另外一个容易被忽略的登录普通用户账户后如果执行命令需要管理员权限大多数情况下会是“拒绝访问”。因为 SSH 会话默认不是提权状态UAC 的特性在这里依然生效。所以日常使用建议直接用管理员账户登录或者提前想清楚需要执行的命令是否涉及管理员权限。2. 完整安装步骤图形界面和命令行两条路这里给出两种安装方式任选一种就好。我建议新手用图形界面手熟之后用 PowerShell 命令行更快。2.1 通过“可选功能”界面安装 OpenSSH 服务器路径是设置 - 应用 - 可选功能 - 添加功能。在列表里找到“OpenSSH 服务器”选中后安装。这个列表很长直接搜“OpenSSH”比较快。安装过程中不需要重启但建议装完后到服务管理器里确认sshd是否已经出现并运行。这里有一个细节添加功能页面里同时有“OpenSSH 客户端”和“OpenSSH 服务器”。客户端在绝大多数 Windows 10 上默认已装不用重复操作。我们这次的目标是服务器也就是让这台机器接受 SSH 连接的那一半。2.2 用 PowerShell 一条命令完成安装、启动并配置自启用管理员身份打开 PowerShell先检查系统里是否已经存在这些可选功能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接着安装服务端Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0安装完成后启动服务并设置开机自启Start-Service sshd Set-Service -Name sshd -StartupType Automatic这两条命令建议都执行。只Start-Service不设置自启的话重启后服务不会自动运行远程连接就断了。2.3 装完后的检查项安装完成不等于一切就绪我一般会检查三个地方首先是服务状态Get-Service sshd状态应该是Running。然后是端口监听netstat -ano | findstr :22如果有LISTENING状态就说明 sshd 已经在监听。最后检查防火墙规则是否生效Get-NetFirewallRule -Name *OpenSSH* | Format-List DisplayName, Enabled, Profile, Direction, Action如果 DisplayName 里看到OpenSSH-Server-In-TCP且 Enabled 为 True基本就稳了。3. 关键配置sshd_config 在 Windows 里的那些坑配置文件的位置是C:\ProgramData\ssh\sshd_config不是用户目录也不是安装目录。ProgramData 是隐藏目录直接到资源管理器路径栏输入即可打开。3.1 Windows 版 sshd_config 与 Linux 版的差异打开这个文件整体结构和 Linux 上的/etc/ssh/sshd_config非常像注释行很多。但有一个非常具有迷惑性的配置#PermitRootLogin yesWindows 上根本没有 root 账户所以这个配置是个历史遗留的兼容性占位符改它没有实际意义。类似的还有#Subsystem sftp sftp-server.exeWindows 版默认 sftp 子系统的可执行文件是sftp-server.exe与 Linux 的/usr/lib/openssh/sftp-server不同不仔细看容易懵。在修改配置前建议先备份一份原始文件。Windows 上 OpenSSH 对配置文件格式同样敏感写错一个字符可能导致服务无法启动恢复备份是最快的解决办法。下面是我会主动改的几个点PermitRootLogin no PasswordAuthentication yes PubkeyAuthentication yes在 Windows 上没有 rootPermitRootLogin写了也不会生效但保持no是个好习惯。PasswordAuthentication和PubkeyAuthentication按需开启日常实验阶段密码登录最省事正式环境建议转向密钥。3.2 管理员组用户的 authorized_keys 路径一个新手的经典误区这是我在 Windows OpenSSH 上踩过最大的一次坑值得单独拿出来讲。在 Linux 上某个用户的家目录下~/.ssh/authorized_keys就是认证密钥文件。在 Windows 上普通用户的确也遵循类似逻辑C:\Users\用户名\.ssh\authorized_keys。但如果你是管理员组成员情况完全不同。Windows 版 sshd_config 默认有一段被注释掉的配置#Match Group administrators # AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys把这段注释打开后管理员组用户登录时认证密钥文件不读用户目录而是读C:\ProgramData\ssh\administrators_authorized_keys。也就是说如果你以管理员账户登录把自己生成的公钥放进了C:\Users\admin\.ssh\authorized_keyssshd 根本不会去看这个文件而是去找administrators_authorized_keys。找不到就直接拒绝密钥登录然后回退到密码登录。很多教程没有强调这一点导致不少人卡在“明明把密钥放好了却总是提示认证失败”。我的建议是直接把这段配置打开然后把公钥放进全局管理员文件里而不是继续把密钥散落在各管理员用户目录中。3.3 修改默认 Shell 为 PowerShell 或自定义程序连接 Windows OpenSSH 之后默认拿到的交互 Shell 是cmd.exe不是 PowerShell。这一点对 Linux 迁移用户来说很不习惯。其实默认 Shell 是通过注册表决定的键值路径是HKEY_LOCAL_MACHINE\SOFTWARE\OpenSSH\DefaultShell默认情况下这个键甚至不存在sshd 内部会回退到cmd.exe。想改成 PowerShell可以用管理员权限 PowerShell 执行New-Item -Path HKLM:\SOFTWARE\OpenSSH -Force New-ItemProperty -Path HKLM:\SOFTWARE\OpenSSH -Name DefaultShell -Value C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -PropertyType String -Force如果你装了 PowerShell 7路径通常是C:\Program Files\PowerShell\7\pwsh.exe替换成它即可。改完后不需要重启 sshd新连接立刻按新 Shell 操作。需要注意的是这个默认 Shell 只影响交互式会话scp、sftp文件传输走的是子系统流程不受影响。4. 从客户端连过来密码登录与密钥登录的完整实测配置完成后真正的考验才刚刚开始。这里把密码登录和密钥登录两种方式都完整走一遍。4.1 密码登录的准备与实测假设服务端 IP 是192.168.1.100用户名是test。另一台机器上执行ssh test192.168.1.100默认端口 22 可以省略。Windows 端第一次被连接时客户端会提示确认 host key输入yes后回车。看到类似下面的输出testWIN10-PC C:\Users\test说明连接成功。这里的提示符是 cmd 风格说明当前是默认 Shell如果之前修改过默认 Shell就会有对应的提示符。密码登录最大的坑在于连续输错密码Windows OpenSSH 默认继承了系统的账户锁定策略多次失败可能导致账户被临时锁定后续连接一直提示权限错误。遇到这个情况不要急着反复试密码先等锁定时间过去或者在服务端用本地登录方式解锁。4.2 密钥登录的完整链路与权限处理密钥登录流程本身不复杂客户端生成密钥对服务端保存公钥连接时验证签名。但在 Windows 上细节决定成败。客户端生成密钥以 ed25519 为例ssh-keygen -t ed25519 -C windows-remote会生成id_ed25519和id_ed25519.pub两个文件。接下来需要把公钥内容放到服务端。普通用户的路径是C:\Users\用户名\.ssh\authorized_keys管理员组成员尤其是如果按前面说的打开了 Match Group administrators 段路径是C:\ProgramData\ssh\administrators_authorized_keys把公钥内容追加到目标文件时建议使用 VS Code 打开文件并确保换行格式是 LF。Windows 记事本保存的文件默认可能是 CRLF带回车符的\r会被 OpenSSH 解析到密钥内容末尾导致签名验证失败这种问题最让人头疼因为从文件内容上看不出任何区别。更稳妥的方式是用 PowerShell 命令追加比如Add-Content -Path C:\ProgramData\ssh\administrators_authorized_keys -Value ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...但这里有个细节传统 Windows PowerShell 的Add-Content默认会按 Unicode 编码处理部分场景而 sshd 读取 authorized_keys 时更希望文件是 UTF-8 或纯 ASCII。建议用 UTF-8 编码保存Add-Content -Path C:\Users\test\.ssh\authorized_keys -Value ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... -Encoding ascii权限方面还应该确保服务端C:\ProgramData\ssh\administrators_authorized_keys文件的安全性设置足够严格。默认情况下它只允许 SYSTEM 和 Administrators 完全控制如果过程中手动开放过普通用户读取权限sshd 会在日志里报一个权限过大的错误并直接忽略这个文件。可以通过 icacls 重新设置icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant SYSTEM:(R) /grant Administrators:(R)完成后在客户端重新连接ssh -i ~/.ssh/id_ed25519 test192.168.1.100如果顺利不再提示输入密码直接进入会话。4.3 从 Windows 客户端到 Windows 服务端的 scp/sftp 实测很多人的实际使用场景是文件传输而不仅是敲命令。Windows 10 自带 OpenSSH 客户端因此你既可以用 scp 也可以用 sftp。从 Windows 命令行复制本地文件到服务端scp D:\logs\app.log test192.168.1.100:C:/Users/test/logs/app.log注意目标路径的写法Windows 下的C:\Users\...在 scp 命令里最好改写成C:/Users/...否则反斜杠会被当成转义字符或路径分隔符产生歧义。拉取文件则反过来scp test192.168.1.100:C:/Users/test/logs/app.log D:\logs\sftp 交互式会话也类似sftp test192.168.1.100进去之后就是熟悉的get、put命令。实测下来文件传输速度稳定和 Linux 间互传没有明显差别。5. 常见故障的排查思路与实证这里把我实际遇到过的、以及帮别人排查过的几类高频问题整理出来。故障排查最重要的是思路而不是背答案。5.1 连接超时先看防火墙再看监听状态客户端执行ssh test192.168.1.100后如果一直卡住直到超时属于典型的网络层问题。按照优先顺序排查第一步确认服务端sshd有没有监听 22 端口netstat -ano | findstr :22如果没有监听回到服务状态检查Get-Service sshd如果服务没起来尝试手动启动Start-Service sshd如果启动失败大概率是配置文件写错了。立刻执行C:\Windows\System32\OpenSSH\sshd.exe -d前台调试模式会直接输出错误信息定位配置问题最快。第二步确认防火墙是否拦截。这里有一个很常见的细节Windows 防火墙的规则是按“配置文件”区分的。同一块网卡如果在网络连接设置里被标记为“公用网络”而防火墙规则只对“专用网络”生效那连接自然会被拦。可以先临时在防火墙高级设置里给OpenSSH-Server-In-TCP规则勾选所有配置文件验证问题是否解决。确认是规则作用域问题后再进一步收紧。第三步检查服务端是否真的监听了对外 IP。如果你修改了ListenAddress或者机器上有多张网卡需要确认监听地址是否正确。用下面命令查看具体监听地址Get-NetTCPConnection -LocalPort 22 | Select-Object LocalAddress, LocalPort, State5.2 认证失败我遇到过的高频原因认证失败的可能原因很多但高频的就那么几个。密码登录失败先确认密码本身。Windows 密码允许带一些特殊字符在客户端命令里直接输入时注意终端对!、$、等符号的解释建议先使用交互式密码输入而不是把密码拼在命令行里。密钥认证失败最常见的是 authorized_keys 文件路径不对尤其是管理员账户误用了用户目录下的C:\Users\用户名\.ssh\authorized_keys而实际有效路径是C:\ProgramData\ssh\administrators_authorized_keys。其次是文件编码和换行符导致密钥内容解析异常前面提到过建议用 VS Code 打开确认右下角是 LF而不是 CRLF。再一个容易被忽略的客户端known_hosts缓存冲突。如果服务端重装过系统或者更换过 host key客户端会提示 host key 不匹配并拒绝连接。解决方式是在客户端执行ssh-keygen -R 192.168.1.100清除旧的主机指纹然后重新连接。5.3 查看 OpenSSH 日志的正确方式Windows 上的 OpenSSH 日志不像 Linux 一样记录在/var/log/secure或/var/log/auth.log而是写进事件查看器。打开事件查看器 - 应用程序和服务日志 - OpenSSH - Operational里面记录了 sshd 的详细运行情况。比如配置加载失败、授权文件权限问题、特定账户连接成功或失败等。排查「为什么密钥登录总是回退到密码」时这个日志几乎是唯一可信的信息来源。比如常见的一条错误信息是Invalid users ... or not permitted to login from ...或者针对 authorized_keys 权限的警告。看到日志里提示某个文件权限不安全就可以立刻往 icacls 方向上排查。5.4 升级过 OpenSSH 版本后配置失效怎么办Windows 10 自带的 OpenSSH 版本通常不高如果从微软官方 GitHub 仓库下载了更新版本做替换新旧版本之间配置文件的兼容性需要注意。我遇到过升级后sshd服务无法启动的情况最后定位是配置文件里使用了新版本不认识的指令或者旧版本允许的语法在新版本被移除了。遇到这个问题最简单的处理方式是把配置文件重命名备份让服务用默认配置先启动Rename-Item C:\ProgramData\ssh\sshd_config C:\ProgramData\ssh\sshd_config.bak Restart-Service sshd默认配置可以正常启动后再逐条把之前需要的配置加回来一边加一边检查。这种“二分法”虽然粗暴但比逐行猜要快得多。6. 安全加固与日常维护经验OpenSSH 服务一旦开放到网络安全就是绕不开的话题。Windows 上的加固思路和 Linux 大同小异但有它自己的特点。6.1 关闭密码登录并强制密钥登录在 sshd_config 里修改PasswordAuthentication no PubkeyAuthentication yes保存后重启服务Restart-Service sshd之后只有持有有效私钥的用户才能登录。这个操作在 Windows 上同样有效而且我实测下来非常稳定。但有一个大前提确认你的公钥已经成功放到正确路径并完成过连接测试。如果你把密码登录关掉而密钥还没配置成功那就等于把自己关在门外。我建议的处理顺序是先用密码登录完成密钥配置并验证密钥登录确认没问题后再关密码登录。6.2 修改默认端口和使用来源 IP 限制修改端口能降低大量扫描流量。Windows 版 sshd_config 同样支持修改 PortPort 2222改完要同步修改防火墙规则。如果你之前依赖安装时自动创建的一条规则端口一变那条规则就失效了。可以在 PowerShell 里手动添加针对新端口的规则并限制来源 IPNew-NetFirewallRule -Name OpenSSH-Custom-In -DisplayName OpenSSH Server Custom Port -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 2222 -RemoteAddress 192.168.1.0/24这样即使是公网环境也只有你指定的网段能访问 SSH 端口恶意扫描器的成功率会大幅下降。6.3 私钥、authorized_keys 文件权限的经验客户端上的私钥文件在 Linux 下要求权限不能太开放否则 ssh 会拒绝使用。Windows 自带的 OpenSSH 客户端也有类似机制但报错提示比较隐晦比如“Permissions for id_ed25519 are too open”。在 Windows 上可以用 icacls 修正私钥权限icacls C:\Users\test\.ssh\id_ed25519 /inheritance:r /grant:r %USERNAME%:R服务端的 authorized_keys 文件需要保证除了管理员和 SYSTEM 之外的用户没有写入权限这一点前面已经提过。6.4 当心“管理员即 root”的权限逻辑Windows OpenSSH 针对管理员组有特殊处理这一点既是便利也是风险。管理员组用户登录后不仅密钥文件路径不同权限能力也很大相当于 Linux 的 root 级权限。如果这台 Windows 机器被攻破整个系统基本就暴露了。因此不要用管理员账户做日常低风险操作。建议单独创建一个普通用户并加入Users组用于日常 SSH 连接和文件传输只有需要执行系统级操作时再用管理员账户登录。这算是我在 Windows 环境里比较推荐的做法。另外一点如果某个管理员账户设置了空密码即便通过 SSH 也需要注意系统策略是否允许。为了安全任何暴露到网络的账户都不建议使用空密码或弱密码这是底线。兼容性方面Windows 自带 OpenSSH 对Match User、Match Group这些条件的支持已经比较完善但远不如 Linux 那样被广泛讨论。如果用到复杂的多用户权限隔离建议先在测试环境里充分验证确定符合预期再上正式机器。关于 OpenSSH 日常升级我自己现在的习惯是每季度检查一次微软官方 Windows Server 和 Windows OpenSSH 更新情况。如果有可用的系统更新优先通过 Windows Update 安装如果需要较新的功能特性再从 GitHub 仓库下载 Win32-OpenSSH 发布包手动替换。替换之前先把当前C:\Windows\System32\OpenSSH目录备份一下再把新版文件解压覆盖进去然后重启sshd服务做连通性验证。替换后如果遇到配置不兼容的情况前面提到的恢复备份和“二分法”排查思路是解决这类问题最快的方式。