ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Windows OpenSSH安装与配置:服务端、免密登录及排障实战

Windows OpenSSH安装与配置:服务端、免密登录及排障实战 1. 从一台没有图形界面的Windows Server说起装OpenSSH到底要解决什么几年前接手过一批运维任务其中一台是跑在机房里的Windows Server没有图形界面日常只能靠远程桌面。问题在于业务脚本部署在另一台Linux跳板机上需要定期把生成的报表目录同步过去。RDP传文件慢、断线重连还容易中断最靠谱的做法其实是让这台Windows也能被ssh/scp直接访问。于是就有了这篇内容要聊的事在Windows上安装OpenSSH把服务端和客户端都配起来。OpenSSH在Windows上早已不是外挂级别的存在。从Windows 10 1809和Windows Server 2019开始微软把OpenSSH客户端做成了系统内置组件服务端则以可选功能的形式提供。这意味着大部分情况下你根本不需要去第三方站点下载什么安装包动动命令就能装上。但真到了实操环节坑还是不少有的机器装完服务起不来有的连上了却被立刻踢掉有的密钥怎么放都不生效。这篇内容适合三类人需要在Windows上开sshd做远程运维的工程师、要写自动化脚本调用ssh/scp的开发、以及接手别人配好的Windows机器但看不懂配置的维护者。下面我会把在线安装、离线部署、配置调整、免密登录和排障这几块拆开讲每一条都尽量说清楚为什么这么做而不是只丢一串命令。提示Windows上的OpenSSH分为客户端和服务端两个独立组件装了客户端不代表能当服务器用这是最常见的认知偏差后面会单独展开。2. 动手前先摸清底数客户端和服务端各在不在2.1 一条命令看清两个组件的安装状态很多人一上来就敲ssh命令发现能用就以为服务端也装好了。实际上内置的那份只是客户端用来从Windows连别人要让别人连进这台Windows得额外装OpenSSH Server。判断方法很简单用管理员权限打开PowerShell执行Get-WindowsCapability -Online | Where-Object Name -like OpenSSH*输出里会出现两行形如OpenSSH.Client~~~~0.0.1.0和OpenSSH.Server~~~~0.0.1.0后面的State字段会显示Installed或NotPresent。这一步的价值在于先确定你要装的是哪一个避免装完发现方向错了。我见过有人折腾半天服务端结果他的需求只是从Windows连Linux装个客户端就够了。顺便再确认一下版本ssh -V这条命令会打印类似OpenSSH_for_Windows_8.6p1, LibreSSL 3.4.2的信息。记下这个版本号后面排查兼容性问题时要用到。2.2 Windows版本与OpenSSH能力的对应关系不同Windows版本能拿到的OpenSSH版本差别不小这直接影响你能用哪些特性。比如较老的Windows Server 2016系统自带的可选功能里根本没有OpenSSH条目只能走离线安装那条路。而Windows 10 1809之后的版本内置的客户端版本会随系统更新一起走。系统版本内置客户端可选功能服务端建议做法Windows 10 1809有有直接在线安装Windows Server 2019有有直接在线安装Windows Server 2016无无离线部署Win32-OpenSSHWindows 7 / 2008 R2无无离线部署且要注意API兼容注意Windows Server 2016这类系统里即便你手动补了OpenSSH的二进制文件也可能因为缺少某些系统调用而出现服务启动失败。这种时候优先考虑升级系统或用文件同步类工具替代不要硬扛。这里补一个经验如果你拿到的是一台加固过的机器可选功能列表可能是被策略裁剪过的Get-WindowsCapability返回空或者报错。遇到这种情况直接跳到离线安装那一节别在在线路径上耗时间。3. 在线安装从可选功能到服务真正跑起来3.1 图形界面路径适合偶尔用一次的人路径是设置 → 应用 → 可选功能 → 添加功能在搜索框里输入OpenSSH会看到OpenSSH 客户端和OpenSSH 服务器两个条目选中服务器那个点安装即可。整个过程一两分钟适合只是临时搭个环境、不想记命令的人。缺点是图形界面在Server Core版本上是没有的而且批量部署时效率太低。3.2 PowerShell命令才是批量部署的正解实际工作中我更推荐命令行一是可复制、可写进脚本二是能明确知道每一步的结果# 安装服务端 Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 # 安装客户端如果确实没装 Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0执行完看到Online : True、RestartNeeded : False就算成功了。如果安装中途失败或者状态卡在InstallPending可以用修复命令重置一下Repair-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0需要卸载时把动词换成Remove-WindowsCapability即可注意卸载服务端会一并移除C:\ProgramData\ssh下的配置操作前先备份。3.3 服务启动、开机自启与默认Shell三件事装完只是文件到位服务还得手动拉起来并且设置成开机自启否则重启一次就失效Start-Service sshd Set-Service -Name sshd -StartupType Automatic Get-Service sshd第三行用来确认状态是Running。这一步做完理论上已经可以从别的机器ssh连过来了但连接进去后大概率会看到一个黑漆漆的cmd窗口因为Windows版sshd的默认Shell是cmd.exe。想换成PowerShell改注册表New-ItemProperty -Path HKLM:\SOFTWARE\OpenSSH -Name DefaultShell -Value C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -PropertyType String -Force改完不需要重启服务下次新建连接就会生效。为什么要费这一步因为cmd对管道、变量展开、脚本执行的支持都很弱你ssh过去本来就是要跑脚本或做批量操作的用cmd会处处受限。这个细节很多教程都不提但实际用起来差别很大。4. 离线安装把Win32-OpenSSH手工搬进目标机器4.1 取包这件事要走官方渠道完全断网的机器没法用可选功能。这时需要从微软官方的PowerShell/Win32-OpenSSH项目页面下载对应版本的zip包比如OpenSSH-Win64.zip。下载时注意区分x64和x86虽然现在x86的机器很少但老设备上确实存在。拿到包之后建议在有网络的机器上先解压检查一下目录结构确认里面有sshd.exe、ssh.exe、install-sshd.ps1这几个关键文件再拷进内网。拷进去的方式可以用U盘也可以走堡垒机的中转目录。我个人的做法是先把包放到C:\Users\Public\Downloads这类公共路径解压验证完再挪到最终位置避免解压一半发现包损坏又要重新拷贝。4.2 定位解压与注册服务最终目录我一般放在C:\Program Files\OpenSSH路径里不要有空格和中文否则某些脚本调用会出现诡异问题。解压完成后进入该目录用管理员权限的PowerShell执行powershell.exe -ExecutionPolicy Bypass -File .\install-sshd.ps1这个脚本会做几件事注册sshd服务、生成主机密钥、调整文件权限、设置服务为手动启动。执行完再重复上一节的服务启动和自启设置然后把C:\Program Files\OpenSSH加进系统PATH这样在任何目录下都能直接调用ssh/scp。$env:Path ;C:\Program Files\OpenSSH [Environment]::SetEnvironmentVariable(Path, $env:Path, Machine)4.3 权限、路径与两个容易翻车的点离线安装最常见的两个问题第一个是脚本执行被策略拦下。如果你看到无法加载文件因为在此系统上禁止运行脚本说明ExecutionPolicy是Restricted上面那条命令里的-ExecutionPolicy Bypass就是专门绕开这个限制的。第二个是主机密钥生成失败通常是因为解压目录的权限不对或者解压时用了普通用户身份导致后续服务账户没权限读密钥文件。提示离线安装的版本不会随系统更新自动升级后面出现安全公告时需要你手动替换文件建议把这个目录和版本号记进资产台账。还有一点值得说手动部署的版本配置文件的默认路径依然是C:\ProgramData\ssh而不是安装目录。很多人改错了地方的sshd_config改完发现不生效就是踩了这个坑。5. sshd_config里真正需要动的几行5.1 默认值逐条过一遍别整份照抄别人的C:\ProgramData\ssh\sshd_config是服务端的主配置。网上有很多优化模板动辄几十行改动我实测下来大部分是没必要的。真正值得关注的就这么几项配置项默认值建议原因Port22按需改端口冲突时改改了要同步防火墙PasswordAuthenticationyes视情况只走密钥就关掉PubkeyAuthenticationyes保持免密登录的基础PermitRootLogin无不适用Windows没有root概念可忽略Subsystem sftp已配置保持scp/sftp依赖它改完配置一定要用Restart-Service sshd重启服务光reload在某些版本上不生效。改之前先备份一份原文件出问题能快速回滚。5.2 主机密钥生成与更换主机密钥的默认位置在C:\ProgramData\ssh\包括ssh_host_rsa_key、ssh_host_ed25519_key等。首次安装脚本会自动生成不需要你操心。但如果你把机器做了克隆虚拟机模板那种两台机器的主机密钥会完全一样客户端连接时就会报远程主机标识已更改的警告。这时候需要删掉旧密钥重新生成Remove-Item C:\ProgramData\ssh\ssh_host_* ssh-keygen -t rsa -f C:\ProgramData\ssh\ssh_host_rsa_key -N ssh-keygen -t ed25519 -f C:\ProgramData\ssh\ssh_host_ed25519_key -N Restart-Service sshd客户端那边的known_hosts也要清理对应条目否则一直报警告。这个坑在批量部署虚拟机模板时几乎必踩提前规避能省不少事。5.3 防火墙放行与端口连通性验证服务起来了但连不上十有八九是防火墙。较新版本的安装流程会自动创建一条入站规则名字一般叫OpenSSH-Server-In-TCP。用这条命令确认Get-NetFirewallRule -Name *ssh*如果查不到手动补一条New-NetFirewallRule -Name sshd -DisplayName OpenSSH Server (sshd) -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22验证连通性别只靠直觉按顺序来先在服务器本机Test-NetConnection -ComputerName localhost -Port 22确认服务在监听再从客户端Test-NetConnection -ComputerName 服务器IP -Port 22这一步能区分是网络不通还是服务没起。这两步分开做能省掉大量瞎猜的时间。6. 客户端那边的功夫密钥、config与免密登录6.1 密钥对生成与公钥落到哪里免密登录的核心是公钥放置位置正确。先生成密钥对ssh-keygen -t ed25519 -C win-server-01一路回车即可私钥默认在%USERPROFILE%\.ssh\id_ed25519。然后把公钥内容追加到服务端的授权文件里。这里有个Windows特有的坑普通用户和管理员用户用的授权文件不是同一个。普通用户放在自己的%USERPROFILE%\.ssh\authorized_keys而管理员组成员统一读C:\ProgramData\ssh\administrators_authorized_keys。这个规则写在sshd_config末尾的Match块里Match Group administrators AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys很多人配了半天免密不生效就是因为把公钥放进了个人目录但登录的账户属于管理员组sshd根本不看那个文件。这个细节值得单独记一笔。6.2 用config文件把连接参数固化下来每次敲完整命令太累在客户端%USERPROFILE%\.ssh\config里配置别名Host win01 HostName 192.168.1.50 User opsadmin Port 22 IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60 ServerAliveCountMax 3配完之后ssh win01就能直接连。ServerAliveInterval这两个参数是专门对付闲置一会儿就被断开的问题很多网络设备会清理长时间无流量的会话加了这个会定时发心跳保活。6.3 权限不对导致密钥被忽略的排查Windows版的OpenSSH对administrators_authorized_keys的ACL要求很严格只允许Administrators组和SYSTEM账户访问多了任何其他账户或继承权限sshd就会直接忽略这个文件且日志里给的信息很模糊。修正命令icacls.exe C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant Administrators:F /grant SYSTEM:F执行完可以再用icacls看一下结果确认没有多余条目。这个问题的隐蔽之处在于文件内容明明是对的客户端却一直提示要输密码而服务端日志只写一句认证失败不告诉你原因是权限。我第一次遇到时查了快一个小时。7. 排障实录连不上、连上被踢、版本对不上7.1 连接被拒的三层排查顺序遇到Connection refused或Connection timed out按这个顺序走别跳步服务层Get-Service sshd看服务在不在跑。不在跑就Start-Service起不来就去看事件日志。监听层netstat -ano | findstr :22看端口有没有被监听。如果被别的进程占了要么改Port要么停掉那个进程。网络层从客户端Test-NetConnection测端口。不通就是防火墙或安全组的问题。三层里最容易忽略的是第二层。有一次排查半天最后发现是另一款软件占了22端口sshd启动时直接失败退出但服务状态显示得很含糊。7.2 日志到底该看哪里Windows版sshd的日志默认走Windows事件日志位置在事件查看器 → 应用程序和服务日志 → OpenSSH → Operational。连不上、认证失败的具体原因基本都能在这里找到。如果觉得事件查看器点来点去麻烦也可以用PowerShell直接过滤Get-WinEvent -LogName OpenSSH/Operational -MaxEvents 50 | Where-Object { $_.LevelDisplayName -in Error,Warning } | Format-List TimeCreated, Message调高日志详细程度可以在sshd_config里加LogLevel VERBOSE调试完记得改回去不然日志量会涨得很快。7.3 升级之后配置不兼容怎么办OpenSSH的版本迭代比较快新版会对某些老配置项告警甚至拒绝启动。比如某些加密算法被标记为弱算法后老配置里还写着就会报错。处理思路是先看服务启动失败的报错里点名了哪个配置项再去对应版本的发行说明里查这个项的状态。常见做法是注释掉过时项交给默认值处理而不是强行保留。注意升级前务必备份C:\ProgramData\ssh整个目录包括配置和主机密钥。有些升级流程会覆盖配置回滚时没有备份会很麻烦。另外客户端和服务端版本不需要完全一致但跨大版本太多时可能出现算法协商失败表现为连接建立到一半就断开日志里能看到no matching key exchange method found之类的提示。这时候要么升级客户端要么在服务端显式允许对应算法两种方案各有权衡生产环境优先选前者。8. 把这套东西当长期资产来维护的一点个人习惯配置好之后我建议做三件小事。第一把C:\ProgramData\ssh目录和C:\Program Files\OpenSSH的版本号记进台账下次出现安全公告时能快速定位哪些机器需要处理。第二主机密钥生成后导出一份离线保存机房重装系统时不至于让所有客户端的known_hosts全部失效。第三对只走密钥登录的机器在sshd_config里把PasswordAuthentication关掉减少被暴力尝试的口子同时配合登录失败次数限制。我在实际使用中发现Windows上的OpenSSH真正麻烦的从来不是装这个动作本身而是装完之后那一堆权限、路径、组匹配的细节。把上面这些点过一遍后续的维护成本会低很多。至于升级我的习惯是先在测试机上跑一轮确认现有连接方式都能用再推到生产毕竟这玩意儿一旦挂掉远程运维的通道就断了代价不小。
返回列表