
搞 Windows 运维的人迟早都会碰到要给 Windows 机器开 SSH 的需求。我在好几个项目里都遇到过这种情况要么是机房里的 Windows Server 需要统一纳管要么是开发机要从 Linux 跳板机过去传文件再要么是 Git 要连 Windows 上的仓库。以前大家习惯用某些远程桌面或者 FTP 凑合但真正进了生产环境什么协议都不如 SSH 干净、安全、可控。这个需求的答案其实很明确Windows 自带的 OpenSSH。但真正折腾起来在线装和离线装完全是两套路子。在线装很简单点几下鼠标或者敲一条命令就行离线装要面对一堆依赖和权限问题稍不注意就会卡在进度条上。这篇文章我把两条路都走一遍把命令、参数、报错、排查方法都整理清楚给需要的人当个参考。1. 动手前先想清楚Windows上的OpenSSH到底能解决什么问题1.1 为什么要在Windows上部署OpenSSH很多人对 Windows 上开 SSH 的第一反应是“没必要”。但实际上只要你的环境里同时存在 Linux 和 Windows 机器SSH 几乎是打通这两种系统最省事的桥。先说远程管理。Windows 自带的远程桌面RDP确实好用但它是图形界面协议带宽占用大而且很多内网环境会限制 3389 端口。OpenSSH 基于命令行走 22 端口只要网络策略允许 TCP 流量你就能用ssh userhost直接进去执行命令查看服务状态、重启服务、拉日志全部可以用脚本完成。我在一个混合机房项目里几十台 Windows 服务器全靠 SSH 统一跑巡检命令比挨个开远程桌面效率高出一个量级。再说文件传输。Windows 上传统做法是开 SMB 共享或者架 FTP 服务器但这两者在公网环境里安全性都不够看而且配置繁琐。SSH 自带 SFTP 子系统只要装好 OpenSSH你就能用任何支持 SFTP 的客户端FileZilla、WinSCP、甚至命令行 scp直接传文件走的是和 SSH 同一套加密通道不需要额外开放端口。还有一个场景是密钥登录。Windows 的 OpenSSH 支持公钥认证你可以生成一对密钥把公钥放到 Windows 用户的authorized_keys文件里之后登录就不需要密码了。这对自动化运维来说很重要脚本里不用硬编码密码安全性提升很多。1.2 在线安装与离线安装两条路线怎么选这个问题的答案取决于你的机器能不能访问互联网。在线安装适合那些能连通微软更新服务器或者可以访问互联网的开发机、测试机。优点是一条命令装完自动处理依赖版本也是最新的。缺点是如果你的内网策略很严格根本连不出去那就走不通。离线安装适合内网服务器、生产环境、还有一些等保要求严格的网络。这些机器一般不能访问外网只能通过介质拷贝安装文件。离线安装的难点不在于拷贝本身而在于找对安装包、带上所有依赖、处理安装权限。这两个场景我在实际工作中都踩过不少坑下面分别把步骤和注意事项讲透。2. 在线安装OpenSSH图形界面与命令行双方案2.1 图形化安装全流程如果是单台机器偶尔用一次图形化方式最直观。按Win I打开系统设置进入“应用” - “可选功能”然后点击“添加可选功能”按钮。系统会加载功能列表这时候在搜索框里输入OpenSSH就能看到结果。列表里一般会出现两个条目OpenSSH 客户端提供ssh、scp、sftp等命令用来连接其他 SSH 服务。OpenSSH 服务器提供sshd服务让其他机器能连到这台 Windows 上来。如果你只是需要从这台机器去连别人装客户端就够了如果你要被别人连或者打算把 Windows 当作跳板机、文件服务器那就必须装服务器组件。大多数运维场景下两个都装。点击“安装”之后等待进度条走完这个过程根据网络状况和系统负载一般几十秒到几分钟。装完之后不需要重启但建议打开 PowerShell 验证一下。注意如果你在“可用功能”列表里搜不到 OpenSSH大概率是系统版本问题。OpenSSH 是 Windows 10 1809 和 Windows Server 2019 开始作为可选功能引入的如果你的系统是更老的版本建议直接走 3.2 节的离线方案。2.2 用PowerShell命令行装更符合运维习惯图形化安装只适合一台两台一旦机器数量多起来或者你打算把安装步骤写进自动化脚本命令行才是正确的打开方式。用管理员权限打开 PowerShell首先可以用一条命令检查系统是否已经内置了 OpenSSH 功能Get-WindowsCapability -Online | Where-Object Name -like OpenSSH*如果系统还没安装过输出的状态State列会是NotPresent。如果显示Installed说明之前已经装过了不需要重复操作。确认状态之后安装服务端和客户端各只需一条命令Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0注意命令中的~~~~0.0.1.0是组件版本号正常执行时不用修改系统会拉取功能包。执行完如果看到RestartNeeded: False就表示不需要重启状态已经变成Installed。我在实际执行这条命令时偶尔会遇到一种情况网络是通的但命令运行几分钟后返回一个错误提示无法从 Windows Update 下载内容。这种情况一般是系统的更新服务Windows Update没有启动或者组策略禁止了 Windows Update 的网络访问。解决办法是在服务管理器里确认Windows Update服务状态为“正在运行”再重新执行命令。2.3 在线安装后的基本状态检查无论用哪种方式安装安装完成后需要手动启动服务并将服务设置为“自动”启动类型否则重启机器后sshd不会自动运行。在管理员 PowerShell 中执行以下命令Start-Service sshd Set-Service -Name sshd -StartupType Automatic Get-Service sshd最后一条Get-Service用来确认服务状态正常情况下Status列会显示Running。另外可以用ssh localhost做一次本机回环测试首次连接会提示确认指纹信息输入yes回车再输入当前用户的密码。如果能够正常显示 Windows 的命令行提示符说明服务端基本工作正常。提示Windows 默认的 SSH 监听端口是 22和 Linux 一致。如果系统防火墙没有自动放行 22 端口外网机器是连不进来的这点在后面的章节我会详细说明。3. 无网环境的离线安装方案3.1 离线安装的核心思路换台机器取“货”离线安装的场景我很熟悉通常是在内网机房里机器没有外网权限但你又必须让它提供 SSH 服务。这时候的核心思路就一句话找一台能上网的机器把安装包下载下来然后用 U 盘、内网文件服务器或者远程桌面拷贝等方式把安装包传到目标机器上。Windows 的 OpenSSH 离线安装有两种主流途径一种是从 GitHub 下载 MSI 安装包手工安装另一种是提取 Windows 自带功能的 cab 包。这里我更推荐第一种因为 MSI 包是微软官方提供的 OpenSSH for Windows 发行版安装流程和依赖处理都比较规范遇到问题的概率小很多。GitHub 上可以找到微软官方的 OpenSSH for Windows 发布页面其中.msi后缀的文件就是可用的安装包。文件名一般分为两个部分OpenSSH-Win64.msi对应 64 位系统OpenSSH-Win32.msi对应 32 位系统。现代 Windows 基本都是 64 位直接拿 64 位版本就行。注意下载时留意一下版本号和发布时间尽量选择正式稳定版而不是 RC 候选版。选包的时候也要注意上下载页面的坑别下成源码包。3.2 MSI包安装的完整操作与参数说明打包好的 MSI 拷贝到目标机器上之后安装过程可以双击完成但我更推荐用命令行方式因为能带参数也方便写进部署脚本。管理员权限打开 PowerShell 或者 CMD切换到 MSI 文件所在目录执行msiexec.exe /i OpenSSH-Win64.msi /qn/i表示安装/qn表示静默模式全程无界面安装结束自动退出。如果在安装时还想指定安装路径可以加INSTALLDIR参数msiexec.exe /i OpenSSH-Win64.msi /qn INSTALLDIRC:\Program Files\OpenSSHMSI 默认安装路径是C:\Program Files\OpenSSH一般不用刻意修改保持默认反而更省事。安装完成之后有一个关键动作把C:\Program Files\OpenSSH这个目录加进系统的PATH环境变量。不做这步的话你开一个命令行窗口敲ssh是找不到命令的。可以用下面这条命令临时添加当前会话有效$env:Path ;C:\Program Files\OpenSSH但如果要永久生效需要在系统属性面板的环境变量里手动加或者用 PowerShell 把路径写进系统PATH[Environment]::SetEnvironmentVariable(Path, $env:Path ;C:\Program Files\OpenSSH, Machine)3.3 离线下可能踩的坑依赖与权限离线安装最大的坑往往不是 MSI 包本身而是安装前后的环境问题。第一是安装依赖。如果目标机器缺少Microsoft Visual C Redistributable运行库MSI 安装过程可能报错或者安装了却无法运行。解决办法是下载对应位数的 VC Redistributable 离线安装包一起拷过去先装运行库再装 OpenSSH。判断是否缺少这个依赖一般安装报错时会直接提示缺少某个VCRUNTIME140.dll之类的文件。第二是权限问题。安装过程中如果 UAC用户账户控制弹窗被系统策略拦截或者当前用户不是管理员组成员MSI 执行时会报“安装中止”之类的错误。务必要用管理员身份的 PowerShell 或者 CMD 来跑msiexec命令。第三是服务注册问题。MSI 安装完成后sshd服务一般是自动注册的但少数情况下服务没有注册成功。这时候不用重新安装可以直接手动注册服务。在管理员 PowerShell 中执行cd C:\Program Files\OpenSSH powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1这个 PowerShell 脚本会创建sshd和ssh-agent两个服务。之后再确认一下服务是否存在Get-Service sshd如果显示不存在就需要检查安装目录下是否有install-sshd.ps1文件没有的话说明安装动作并未真正完成。我还遇到过一种情况安装包明明是正确的 64 位版本安装时却提示“系统不支持”。后来发现那台机器装的是精简版系统被精简掉了不少系统组件。这种环境只能考虑换标准版系统或者用 32 位版本碰碰运气但一般不推荐在精简系统上折腾。4. 安装完成后的关键配置4.1 服务自启与防火墙放行装好 OpenSSH 只是第一步真正让人放心使用的是把服务启停策略和防火墙规则都配好。服务自启这块在线安装和离线安装都需要手动设置因为我见过不少装了 MSI 包之后服务状态正常、但重启就丢失的情况。在管理员 PowerShell 中一次性搞定Set-Service -Name sshd -StartupType Automatic Start-Service sshd防火墙放行是另一个容易忽略的点。Windows 默认防火墙会拦截入站的 22 端口流量即使服务跑起来了外部机器也连不上。最简单的方法是使用 PowerShell 添加规则New-NetFirewallRule -Name OpenSSH-Server -DisplayName OpenSSH Server (sshd) -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22这条命令会新建一个入站规则放行 TCP 22 端口。执行后可以用Get-NetFirewallRule -Name OpenSSH-Server确认规则状态。提示如果你的 Windows 机器上装了第三方安全软件比如 360、火绒或者企业版终端管理软件光是系统防火墙放行还不够这些软件自带的主防规则也可能拦截 sshd 进程的监听行为。轻则外网连不上重则 sshd 直接启动失败。遇到这种情况需要在安全软件里把sshd.exe加入信任或者放行 22 端口的入站流量。4.2 用密钥登录替代密码登录Windows OpenSSH 完全支持公钥认证但配置方式和 Linux 有一点细节上的差异很多从 Linux 转过来的运维人员会卡在这里。首先在客户端机器上生成密钥对。如果本地有 Linux 环境直接执行ssh-keygen -t ed25519 -C your_email即可。如果是在 Windows 的 PowerShell 里生成密钥就需要先确认 OpenSSH 客户端已经安装好了。生成命令一样ssh-keygen -t ed25519 -C userhost生成的公钥默认在C:\Users\你的用户名\.ssh\id_ed25519.pub私钥在id_ed25519。公钥可以分发私钥绝对不能离开自己的电脑。然后把公钥内容添加到 Windows 目标机器对应用户的authorized_keys文件里。Windows 下authorized_keys的位置和 Linux 不在同一个路径它在用户目录的C:\Users\用户名\.ssh\authorized_keys下。添加公钥的命令Add-Content $env:USERPROFILE\.ssh\authorized_keys ssh-ed25519 AAAA... your_public_key这里有一个非常容易踩坑的点C:\Users\用户名\.ssh这个目录不一定存在。如果不存在先用New-Item -ItemType Directory -Path $env:USERPROFILE\.ssh创建目录。另外authorized_keys文件必须放在对应用户自己的目录下不能放在系统管理员共用目录下。比如你用普通用户zhangsan登录公钥就必须放在C:\Users\zhangsan\.ssh\authorized_keys。配置完成后可能还需要处理一下 OpenSSH 的配置。默认情况下 Windows 的 sshd 是允许公钥认证的但如果你登录的账号是管理员组成员Windows 默认策略是“仅允许通过公钥认证登录管理员账户”。这句话很多人理解反了它意思是管理员账号不能用公钥登录必须用密码登录除非你在sshd_config里显式加上一句话# 文件位置C:\ProgramData\ssh\sshd_config Match Group administrators AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys这个默认配置的本意是更安全的锁定管理员登录但它和很多人心里预期的“有公钥就能登录”冲突。如果不改这个配置用管理员账号测试密钥登录就会发现一直要密码。解决办法有两种。最简单的不用管理员账号登录新建一个普通 user 账号来用或者如果你坚持要管理员密钥登录就把上面的Match Group administrators那一段的AuthorizedKeysFile改成普通用户的标准路径。但我不推荐第二种因为会降低安全性密码加管理员权限的组合反而更稳妥。4.3 修改端口与多实例的建议默认的 22 端口在某些内网环境下可能会被安全基线扫描报告问题等保测出来 22 端口暴露也会算一个风险项。虽然 Windows 上修改默认端口的操作不如 Linux 方便但还是可以做的。配置文件位置在C:\ProgramData\ssh\sshd_config。用记事本或者 VS Code 打开这个文件找到这一行#Port 22把注释删掉把22改成你想要的端口比如2222Port 2222改完保存然后重启 sshd 服务使配置生效Restart-Service sshd注意该配置文件是全局生效的。如果是单实例使用改端口就可以了如果你希望同一台机器上同时监听多个端口Windows OpenSSH 本身不直接支持但可以通过注册多个服务实例的方式实现过程比较麻烦实际用到的场景也很少我这里就不展开了。改完端口后客户端连接也要指定对应端口ssh -p 2222 userhost经验之谈不要用太冷门的端口比如 2222 已经快变成公认的默认备选端口了扫描器都会先扫 22、2222、22022 这些常规位置。如果真要改选一个 10000 的不常用高位端口配合强密码或者密钥登录。5. 常见问题与排查实录5.1 在线安装时提示功能不可用症状用Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0安装时报错提示“无法找到所需的文件”或者“拒绝访问”。排查思路分两步。第一步确定 Windows 更新服务是否可用。检查服务管理器里Windows Update服务状态手动启动后重试。第二步检查系统时间。如果系统时间和真实时间偏差超过几分钟Windows Update 组件连接微软服务器时会出现证书验证失败从而导致安装报错。这个问题我很早以前吃过一次大亏排查到后面才发现是主板电池没电导致时间歪到了十年前。5.2 离线安装卡在0%或失败症状双击 MSI 或者执行msiexec /i OpenSSH-Win64.msi /qn后界面卡在 0%或者瞬间退出且没有输出。如果静默安装时卡住先尝试去掉/qn参数改成有界面的安装方式msiexec.exe /i OpenSSH-Win64.msi这样能看到安装进度和具体的错误信息。一般常见报错有“需要提升权限”说明当前不是管理员“磁盘空间不足”还有“安装程序被组策略禁用”检查目标机器是否有碍事的软件分发策略。另外一个比较隐蔽的坑如果机器之前已经装过老版本的 OpenSSH MSI新版本安装可能因为版本回滚规则而被拒绝。解决办法是先卸载旧版本msiexec.exe /x OpenSSH-Win64.msi /qn然后再安装新版本。5.3 服务启动失败日志在哪看症状服务状态是Stopped手动执行Start-Service sshd报错提示服务无法启动或者立即停止。排查这类问题第一件事是看 Windows 事件查看器。运行eventvwr.msc展开“Windows 日志” - “应用程序”在右侧按事件来源筛选sshd相关错误日志都会记录在这里。常见原因是 SSH 配置文件格式出问题。Windows 的sshd_config解析规则比 Linux 严格一点某些配置项如果写错位置或者格式不对服务启动就会失败。可以把配置文件里改动过的项先全部注释掉改成默认状态再逐步开启直到找到问题项。另外一个常见原因是sshd进程需要访问文件系统上的密钥文件但由于权限问题被拒绝。Windows 的事件查看器会记录类似sshd: PID xxx: error: systemd调用未配置或失败等信息实际报错会接近Permission denied。这时候检查C:\ProgramData\ssh\目录的权限确认SYSTEM用户和Administrators组对该目录有完整控制权限。5.4 安全日志与登录事件分析Windows 的 OpenSSH 登录行为有自己的审计通道但很多运维人员不知道从哪里看。先说登录成功与否。OpenSSH 自身的登录尝试日志会写到事件查看器的“应用程序”日志里事件来源是sshd。事件 ID 可以参考下表快速定位问题方向。事件类型含义常见原因提示输入密码服务端要求客户端认证公钥未匹配或密码错误身份验证成功登录成功正常事件身份验证失败密码错误或密钥不匹配检查密码、公钥连接被关闭客户端断开网络中断或认证超时不允许使用空密码密码策略限制修改 sshd_config 相关条款如果你还想审计“谁在什么时间通过 SSH 登录过系统”可以从 Windows 安全日志中查看登录事件 4624成功登录和 4625失败登录。注意区分安全日志只记录 Windows 账号的登录行为未必会和sshd日志一一对应两者配合查看效果最好。我自己的习惯是在 Windows 上搭建一个日志采集把sshd的应用日志和 4624/4625 安全日志都汇总到中央日志系统方便事后追溯。如果条件不允许那至少在sshd_config里开启详细日志LogLevel VERBOSE然后重启服务排查问题时能看到更详细的认证流程日志。5.5 常见问题速查表问题现象大概率原因处理动作安装命令找不到模块Windows 版本过低或系统精简走离线 MSI 安装22 端口外部连不上防火墙拦截添加防火墙入站规则公钥登录一直要密码管理员组策略限制新建普通用户或调整 Match Group 配置sshd 启动后立即退出sshd_config 配置错误注释改动项逐步恢复服务存在但没启动未设开机自启Set-Service 设置 Automatic从 Linux scp 报错用户名带空格或路径问题加引号处理路径6. 一点个人体会和扩展玩法Windows 上跑 OpenSSH 这件事说难不难说简单也绝对不简单。我最早的几次尝试都卡在配置权限和防火墙这些顺手的事情上后来总结经验才发现主要问题不是技术门槛高而是 Windows 和 Linux 的 SSH 生态在细节上差别很大比如authorized_keys路径、管理员组策略、防火墙配置方式每一项都值得单独留意。如果单位里有条件我建议在前期就把所有 Windows 机器的补丁版本、系统版本、默认密码策略、公钥体系统一规划好然后通过 PowerShell 脚本把安装步骤固化下来。真正到了批量部署的时候一条脚本跑完几十台机器能省出非常多的时间。再分享一个自己常用的扩展思路Windows OpenSSH 装好之后可以在内网搭一个跳板机用这台 Windows 机器的 SSH 隧道来访问内网的其他服务。具体操作就是在 Linux 跳板机上执行类似ssh -L 8080:内网目标机:80 userwindows跳板机这样一来内网 Web 控制台可以在本地浏览器直接打开整个过程都走 SSH 加密隧道安全性和便利性都很不错。如果你平时维护的就是 Windows 和 Linux 混合环境我真心建议把 OpenSSH 的安装和配置流程做成你自己的标准操作手册至少把在线安装、离线安装、密钥登录这三块吃透。这样无论是日常调试还是紧急排障你都不会手忙脚乱。