Windows Server 配置 OpenSSH:公钥登录与故障排查

发布时间:2026/10/1 19:17:12

Windows Server 配置 OpenSSH:公钥登录与故障排查 凌晨两点机房那台 Windows Server 的应用服务卡死了远程桌面怎么点都连不上你只能干等第二天早上有人进机房按电源键——这种场景在运维圈子里太常见了。远程桌面RDP这条路一旦被网络策略挡掉、被会话数占满、或者被系统更新搞挂手里没有第二条通道的时候人就特别被动。OpenSSH装到 Windows 上本质上就是给自己留一条稳定、轻量、可脚本化的第二条命命令行能进、文件能传、命令能编排还不占图形界面的开销。这篇内容我打算把 Windows 上安装 OpenSSH 这件事从头到尾捋一遍从系统版本能不能装、在线和离线两条路怎么走、服务端配置里哪几行非改不可到公钥登录那两个能把人折腾半天的权限坑都写清楚。不管你是刚接触命令行的新手还是天天跟服务器打交道的运维照着走都能落地。1. 先弄清楚 Windows 上的 OpenSSH 到底是两个什么东西1.1 客户端和服务端装错了等于白干很多人一上来就搜Windows 安装 OpenSSH然后照着第一条结果敲命令装完发现ssh命令能用了就以为大功告成——但你真正想干的是让别的机器连进来那要装的是服务端不是客户端。这两个是完全独立的组件在 Windows 里分别叫OpenSSH Client和OpenSSH Server可以单独装也可以一起装。用最直白的话区分客户端就是我主动去连别人服务端就是别人来连我。你笔记本上要连公司服务器装客户端就够了那台放在机房的 Windows Server 要接受从你笔记本发来的连接就得装服务端。同一台机器两个都装也完全没问题互不冲突。顺便说一句客户端其实大多数情况下根本不用装。Windows 10 1809 之后的版本、Windows 11 全系默认就带客户端了。你打开 PowerShell 敲ssh -V如果回显类似OpenSSH_for_Windows_9.x说明已经有了。真没必要为了一个已经存在的东西去重复安装一遍。1.2 微软维护的 Windows 版和 Linux 上的同源不同形Windows 上这套 OpenSSH 来自 OpenBSD 项目由微软的 PowerShell 团队移植维护Win32-OpenSSH代码同源但运行形态差别不小。Linux 上 sshd 靠/etc/ssh/sshd_config和一堆 PAM 模块用户认证走系统账户体系Windows 上 sshd 是一个标准 Windows 服务认证走的是本地账户或者域账户配置文件落在C:\ProgramData\ssh\sshd_config日志写进事件查看器而不是/var/log/secure。这个差异带来的最直接影响是你在 Linux 上背下来的那套排错经验在 Windows 上有一半不适用。比如 Linux 上看日志靠tail -f /var/log/secureWindows 上得用Get-WinEvent去读OpenSSH/Operational这个事件日志通道。再比如 Linux 上文件和目录的权限是 POSIX 位Windows 上是 ACL所以那个经典的authorized_keys 权限太开放导致拒绝登录的问题在 Windows 上表现成ACL 里有不该有的写权限修法完全不一样。配置文件本身倒是几乎一致Port、PasswordAuthentication、PubkeyAuthentication、Subsystem这些关键字两边通用会 Linux 的话上手很快这点很省心。1.3 什么情况下值得在 Windows 上开 sshd不是所有 Windows 机器都需要装服务端。我自己的判断标准是三条第一这台机器需要被自动化工具碰。比如 CI/CD 流水线要把构建产物推到 Windows 服务器上或者 Ansible、Jenkins 这类工具要批量执行命令。这些工具绝大多数原生就走 SSH走 WinRM 也能干但配置更啰嗦SSH 是阻力最小的路。第二远程桌面不够用或者不可靠。RDP 会话数有限制普通版本同时只允许一个交互会话网络抖动一下画面就卡死带宽占用也大。SSH 一个连接几十 KB 内存掉线重连几乎无感拿来跑长时间任务舒服得多。第三需要一条备份通道。这跟第一点不冲突——我遇到过好几次防火墙策略变更把 3389 封了或者 RDP 服务因为某个更新起不来这时候如果机器上有个 22 端口开着人能立刻进去把问题修了而不是等现场支持。反过来如果这台机器就在你手边、只有一个用户用、也没有任何自动化需求那装服务端属于给自己增加攻击面没必要。2. 动手之前这几项前置检查别跳过2.1 系统版本直接决定你能走哪条安装路这点很多人忽略直接导致了后面一堆为什么我的设置里没有 OpenSSH 这个选项。把版本对应关系说清楚系统版本客户端服务端推荐安装方式Windows 10 1809 及以上内置可选功能可装设置面板或 PowerShellWindows 11 全系内置可选功能可装设置面板或 PowerShellWindows Server 2019内置后期版本才有PowerShell 加可选功能Windows Server 2022 / 2025内置可选功能可装设置面板或 PowerShellWindows Server 2016 及更早无无手工部署官方发布包Windows 7 / 8.1 / Embedded无无手工部署官方发布包Server 2016 是个明显的分水岭。我手上还有几台跑着 2016 的老机器Get-WindowsCapability -Online -Name OpenSSH*敲下去什么都返回不了因为那个年代压根没有这个能力包。这种情况只能走离线手工部署那条路后面第 4 节会详细讲。2.2 端口、账户、权限三件事先探一遍安装之前花两分钟做三个检查能省掉后面一小时的困惑。第一个是端口占用。Windows 上有时候会有别的程序抢先占了 22 端口比如某些第三方 SSH 实现、某些备份软件、甚至杀毒软件的组件。检查命令是Get-NetTCPConnection -LocalPort 22 -ErrorAction SilentlyContinue Get-NetTCPConnection -LocalPort 22 -State Listen -ErrorAction SilentlyContinue如果返回了东西看清楚OwningProcess那一列再Get-Process -Id PID查是什么程序。真有占用要么把那个程序挪走要么把自己的 sshd 换个端口。第二个是账户。Windows 上 sshd 默认允许所有本地账户登录但管理员组Administrators成员和非管理员成员走的是两套完全不同的公钥文件路径这是后面最容易踩的坑先记住这个前提。另外要确认你打算用来登录的账户是不是有密码——空密码账户默认是登不上的。第三个是权限。安装 OpenSSH 服务端、启停服务、改注册表都需要管理员权限的 PowerShell。普通 PowerShell 窗口敲Add-WindowsCapability会直接报拒绝访问这个报错信息有时候还挺不明显的容易让人以为是系统版本问题。2.3 四种安装方式横向对比到底用哪种方式装取决于你的网络环境和运维习惯。我把常见四条路的差异列一下方便对号入座安装方式需要联网版本新鲜度适合场景主要缺点设置面板可选功能是跟随系统更新单机、图形界面可用无法批量、版本偏旧PowerShell/DISM 命令是跟随系统更新批量部署、脚本化老系统不支持官方 MSI 安装包否新离线环境、内网批量需自行维护升级官方 zip 绿色包否新老系统、便携部署、想手动控制要跑初始化脚本步骤多我的习惯是能给新系统走可选功能就走可选功能省事且跟着 Windows 更新自动打补丁只有老系统或者明确要求离线时才动 MSI 和 zip 包。下面分两节把在线和离线两条路都走一遍。3. 在线安装设置面板和命令行两种走法3.1 用设置面板点几下装完这条路适合单机操作、有图形界面的场景全程不需要记命令。路径是设置 → 应用 → 可选功能 → 点击添加功能旁边的查看功能。在搜索框里输入OpenSSH正常情况下会看到两个条目OpenSSH 客户端和OpenSSH 服务器。客户端一般显示已安装服务端显示未安装。勾选你要的那个点下一步再点安装剩下的就等系统自己去 Windows 更新服务器拉包。这里有个小细节值得说一下安装过程实际上是在下载如果 Windows Update 服务被组策略禁用、或者更新源不可达这一步会卡很久然后报错 0x800f0954 之类的错误码。这不是 OpenSSH 的问题是系统更新通道的问题。解决办法一般是用命令行走 DISM指定本地源或者走 WSUS或者干脆换离线包。我遇到过内网机器整片都卡在这一步最后统一改成 MSI 离线部署反而更干脆。安装完不需要重启但服务端装完之后服务默认是手动启动状态的不会自己跑起来这点一定要注意。下一步要去把服务启动起来。3.2 PowerShell 命令行的装法和回显解读批量部署或者习惯命令行的话就这么几条命令。先查状态Get-WindowsCapability -Online -Name OpenSSH*正常返回长这样Name : OpenSSH.Client~~~~0.0.1.0 State : Installed Name : OpenSSH.Server~~~~0.0.1.0 State : NotPresentState只有两个值Installed和NotPresent。看到NotPresent就是没装。装服务端Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0那条~~~~0.0.1.0的尾巴不能省它是能力包版本标识少了会提示找不到包。装客户端就是把名字换成OpenSSH.Client~~~~0.0.1.0。如果 PowerShell 这条路因为系统组件损坏报错可以退回 DISM 试试成功率往往更高DISM /Online /Add-Capability /CapabilityName:OpenSSH.Server~~~~0.0.1.0DISM 的好处是错误信息更具体比如它会明确告诉你源文件找不到还是组件存储损坏方便定位。实在修不动就DISM /Online /Cleanup-Image /RestoreHealth先修组件存储再回来装。3.3 装完必做的三行验证装完之后别急着开防火墙先确认三件事能少走很多弯路。第一行确认命令在不在Get-Command ssh -All Get-Command sshd -All服务端装完之后sshd.exe会被放到C:\Windows\System32\OpenSSH\下这个目录默认就在系统 PATH 里。注意我特意用了-All参数因为很多时候你机器上不止一个ssh.exe——Git for Windows 会带一个、WSL 里有一个、可能还有 msys2 的。-All会把所有能匹配到的列出来顺序就是 PATH 的搜索顺序。这个多份 ssh 的问题后面第 7 节专门讲。第二行确认服务在不在Get-Service sshd正常能看到Status : Stopped、StartType : Manual。装完就是这个状态没启动是正常的。第三行确认防火墙规则有没有被自动创建Get-NetFirewallRule -Name *ssh* | Select-Object Name, DisplayName, Enabled, Direction, Action可选功能方式安装时通常会顺带创建一条叫OpenSSH-Server-In-TCP的入站规则允许 TCP 22 端口进来。如果这条规则不存在或者被禁用了外面是连不上的这个检查能帮你排除一半的连不上问题。4. 离线部署MSI 包和绿色包的完整走法4.1 离线包从哪来怎么校验内网机器、隔离环境、或者 Server 2016 这类老系统都得走离线。安装包来源是微软 PowerShell 团队在公共代码托管平台维护的 Win32-OpenSSH 发布页那里有 MSI 和 zip 两种产物。下载的时候有个选择MSI 适合批量、适合走组策略分发、适合交给不熟命令行的人zip 绿色包适合想手动控制安装位置、或者需要在老系统上折腾的场景。文件命名大概是OpenSSH-Win64-vX.X.X.X.msi和OpenSSH-Win64.zip这种形式注意选Win64而不是Win32除非你确实在跑 32 位系统。下载完之后一定要核对哈希值。发布页上一般会给出 SHA256本地算一遍对比Get-FileHash .\OpenSSH-Win64-vX.X.X.X.msi -Algorithm SHA256这一步看着多余但在内网环境里安装包经常是经由好几台机器接力拷贝进来的中间出错的概率比你想的高。我见过一次拷了一半的 MSI装的时候报了个特别莫名其妙的错误排查了半天才发现是包本身不完整。4.2 MSI 的静默安装和参数说明MSI 的图形安装就是下一步下一步没什么好说的。批量场景下用静默安装msiexec /i OpenSSH-Win64-vX.X.X.X.msi /quiet /norestart msiexec /i OpenSSH-Win64-vX.X.X.X.msi /quiet /norestart ADDLOCALServer,Client第二个命令里的ADDLOCAL参数是选择性安装的核心。MSI 里的功能组件一般有三种Server服务端、Client客户端、ClientAndServer。默认行为有时候只装客户端所以批量部署时最好显式指定免得装完一半机器发现没有 sshd。/quiet是静默不弹窗/norestart是别自动重启。这两个参数组合起来适合放进批处理或者配置管理工具里跑。装完之后 MSI 会自动注册服务但同样地服务依然是手动启动状态。另外 MSI 安装也会自动创建防火墙规则一般不用你操心。4.3 zip 绿色包手工初始化的关键几步老系统上 MSI 有时候会因为系统组件版本不够而失败这时候 zip 绿色包是更稳的选择。步骤稍微多一点但每一步都能控制。先把压缩包解到一个固定目录强烈建议放在C:\Program Files\OpenSSH\不要放在用户目录下、更不要放在桌面上。原因很实际sshd 服务是以一个虚拟账户NT SERVICE\sshd运行的它需要读取这个目录下的可执行文件和配置文件。如果你把它解在某个用户的家目录里那个目录的 ACL 可能把这个虚拟账户挡在外面服务启动时会因为读不到文件而失败报错信息还不直观。解压完之后用管理员权限的 PowerShell 进到那个目录跑初始化脚本cd C:\Program Files\OpenSSH powershell.exe -ExecutionPolicy Bypass -File .\install-sshd.ps1-ExecutionPolicy Bypass这个参数是必须的因为默认执行策略通常不允许跑未签名的脚本不加会直接被拦。脚本跑完之后会做三件事注册sshd和ssh-agent两个服务、设置服务启动类型、根据情况生成主机密钥。如果它提示主机密钥生成失败或者你手工把C:\ProgramData\ssh下的密钥删了可以手工补cd C:\Program Files\OpenSSH .\ssh-keygen.exe -t ed25519 -f C:\ProgramData\ssh\ssh_host_ed25519_key .\ssh-keygen.exe -t rsa -b 3072 -f C:\ProgramData\ssh\ssh_host_rsa_key主机密钥是服务端的身份凭证客户端第一次连接时看到的那个指纹就是它。这几对密钥不能随便换一换所有客户端都会报主机密钥已改变的警告需要重新确认。所以生成之后就当作长期资产对待吧。4.4 老系统上的额外注意点Server 2016 这类老系统还有个坑默认的加密算法套件可能不满足新版 OpenSSH 的要求。具体表现是服务能起来但客户端连接时握手失败报no matching key exchange method found或者no matching host key type found之类的错误。根因是系统的加密库版本比较老缺少一些新算法实现。临时绕过的办法是在客户端侧指定算法ssh -o KexAlgorithmsdiffie-hellman-group14-sha256 -o HostKeyAlgorithmsssh-rsa userhost但这只是绕长期方案还是给系统打上最新的补丁。我这里要提醒一句不要为了连一台老机器就把客户端的加密策略整体降级到最松那等于给所有连接都开了口子。用-o参数针对单次连接做临时放宽或者写进~/.ssh/config里针对那一台主机做例外才是正确的做法。5. 服务端配置让 Windows 真正能被 SSH 连上5.1 sshd_config 里真正需要动的那几行配置文件在C:\ProgramData\ssh\sshd_config。注意是ProgramData不是Program Files这两个名字长得像我见过不止一个人改错了文件改了半天没生效还以为配置不生效。打开之后你会发现大部分行都是注释掉的注释状态意味着使用默认值。真正常改的就这么几行Port 22 PasswordAuthentication yes PubkeyAuthentication yes Subsystem sftp sftp-server.exe Match Group administrators AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys逐条解释一下。Port改端口用默认 22。PasswordAuthentication控制是否允许密码登录上线初期一定要保持 yes等公钥登录验证通过了再考虑关掉否则很容易把自己锁在外面。PubkeyAuthentication控制公钥登录默认开。Subsystem sftp这行是 SFTP 功能的基础Windows 版默认就开了指向sftp-server.exe。这行没了 SFTP 就用不了所以尽量不要删。最后那个Match Group administrators块是 Windows 版独有的东西也是最大的一个坑任何属于管理员组的账户它的授权公钥文件路径会被强制指向C:\ProgramData\ssh\administrators_authorized_keys而不是用户家目录下的.ssh\authorized_keys。这个块在文件末尾位置很显眼但很多人压根不知道它是干嘛的。5.2 服务启动、开机自启、防火墙放行三件套配置改完之后按顺序做这三件事。启动服务Start-Service sshd设置成开机自启Set-Service -Name sshd -StartupType Automatic可选功能的安装脚本通常已经帮你设成自动了但手工部署的场景下需要自己设。服务端最怕的就是机器重启之后人连不上还得等现场支持所以自动启动这个设置别省。防火墙这块可选功能安装一般会创建规则手工部署的得自己加New-NetFirewallRule -Name OpenSSH-Server-In-TCP -DisplayName OpenSSH Server (sshd) -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22如果你改了端口这里的-LocalPort也要跟着改。另外默认情况下这个规则是应用到所有网络配置文件的域、专用、公用如果机器直接暴露在不可信网络里可以加-Profile Domain,Private来限制只在内网生效。改完配置之后要重启服务才生效Restart-Service sshd这里有个操作细节重启 sshd 会把你当前正在使用的 SSH 连接一起断掉。所以远程改配置的时候最好留一个 RDP 会话或者第二个 SSH 连接在手边万一改错了还能进去捞人。这是我在生产环境里养成的习惯被坑过之后特别在意。5.3 默认 Shell 换成 PowerShellWindows 版 sshd 默认给你的 Shell 是cmd.exe。这东西能用但体验很差没有管道操作符的高级用法、没有对象输出、Tab 补全弱、中文编码还容易出问题。换掉它只需要改一个注册表值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体验更好启动更快、跨平台兼容性也强。但要注意一点PowerShell 7 的安装路径会随着大版本变化从 6 到 7 到 7.x 每一个大版本的目录名可能不一样升级之后这个注册表值会失效指向一个不存在的文件然后 SSH 登录就会直接断开。升级完 PowerShell 记得回来检查这一项。还有个说法是这个注册表值只对密码登录生效公钥登录不生效这个说法我实测下来在较新版本上是过时的现在两种登录方式都会读到这个值。如果你确实遇到了公钥登录跑到 cmd 里的情况检查一下是不是账户的 Shell 被单独指定了或者配置里有别的地方覆盖了这个默认值。5.4 公钥登录两个能把人逼疯的权限坑密码登录能用了但真要在生产环境用起来还是得上公钥。Windows 上的公钥登录有两个坑跟 Linux 的逻辑不一样。第一个坑是管理员组用户的密钥路径。前面提到的那个Match Group administrators块效果就是只要你的账户在 Administrators 组里sshd 只会去读C:\ProgramData\ssh\administrators_authorized_keys完全无视你放在C:\Users\用户名\.ssh\authorized_keys里的东西。很多人的排查过程是这样的生成密钥、上传公钥、改权限、重启服务、连接、还是提示输密码然后反复检查自己那个authorized_keys文件怎么都找不出问题——因为它压根没被读过。解决办法就是把公钥内容追加到那个全局文件里$key Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub Add-Content -Path C:\ProgramData\ssh\administrators_authorized_keys -Value $key第二个坑是这个文件的 ACL。Windows 版 sshd 对administrators_authorized_keys的权限检查非常严格要求它只能被 Administrators 和 SYSTEM 两个主体访问且不能有继承来的权限。文件里多出任何一个带写权限的主体sshd 会直接忽略这个文件并且在默认日志级别下什么都不说就让你在那猜。用这个命令把它修干净icacls.exe C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant Administrators:F /grant SYSTEM:F对非管理员用户的普通authorized_keys要求是只有该用户和 SYSTEM 可以访问icacls.exe $env:USERPROFILE\.ssh\authorized_keys /inheritance:r /grant $env:USERNAME:F /grant SYSTEM:F如果你已经装了 OpenSSHUtils 这个 PowerShell 模块可以偷懒让它自动修Install-Module -Force OpenSSHUtils -Scope AllUsers Repair-AuthorizedKeyPermission -FilePath C:\ProgramData\ssh\administrators_authorized_keys我个人的经验是遇到公钥登录失败第一件事就是在客户端加-vvv参数看详细日志。日志里会明确写出来Authentication refused: bad ownership or modes for file或者类似的提示看一眼就知道是权限问题还是路径问题比盲目试强得多。ssh -vvv userhost5.5 SFTP 和文件传输的那些细节SFTP 子系统默认是开的连上就能用sftp userhost进去之后put、get、ls、cd、lcd切换本地目录这些命令跟 Linux 上一样。有个细节是 Windows 路径里的反斜杠在 sftp 客户端里要写成正斜杠或者加引号否则会被当成转义字符处理。上传中文名文件的时候可能会遇到编码问题表现是文件名显示成乱码或者上传失败。这个跟客户端的 locale 设置和 Windows 文件系统的 Unicode 处理有关稳妥做法是尽量避免在传输用的文件名里使用中文和特殊字符用英文加下划线这能规避掉绝大多数莫名其妙的传输失败。另外Windows 上还有一个习惯上的差异值得提一句Windows 管理员做文件操作用的工具通常是资源管理器或者 WinSCP很少直接敲 sftp。这没问题WinSCP 底层也是走 SFTP 协议跟 sshd 的对接没有任何区别。只要你的服务端配置对了图形工具和命令行工具都能连上。6. 客户端实战用 Windows 自带的 ssh 干活6.1 首次连接的指纹确认和 known_hosts第一次连一台新机器会看到类似这样的提示The authenticity of host x.x.x.x (x.x.x.x) cant be established. ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxx. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])?这是让你确认对方的主机密钥。在生产环境里这个指纹应该跟服务端管理员核对一下再输 yes尤其是有安全要求的场景。指纹可以在服务端用这条命令打印出来ssh-keygen -lf C:\ProgramData\ssh\ssh_host_ed25519_key.pub确认之后指纹会被写进C:\Users\用户名\.ssh\known_hosts。下次连接就不会再问。如果哪天服务端重装了或者换了主机密钥你会看到那个吓人的大红警告REMOTE HOST IDENTIFICATION HAS CHANGED这时候要去known_hosts里把对应的那一行删掉确认是合法的变更之后再重连。千万不要养成看到警告直接删文件重连的习惯那个警告本身是有意义的。6.2 把命令缩短config 文件的几个实用写法C:\Users\用户名\.ssh\config这个文件不存在的话可以自己建它是纯文本格式固定。有了它那些又长又难记的连接参数就不用每次敲了Host dev-box HostName 192.168.1.50 User deploy Port 2222 IdentityFile C:\Users\me\.ssh\id_ed25519 Host * ServerAliveInterval 60 ServerAliveCountMax 3 TCPKeepAlive yes配好之后一条ssh dev-box就够了端口、用户名、私钥路径全都自动带上。第二段那个Host *是所有主机的通配配置里面那三行是我强烈建议加上的。ServerAliveInterval的作用是每 60 秒向服务端发一个探测包防止因为中间有防火墙或者 NAT 设备把空闲连接掐掉。默认情况下一个空闲的 SSH 连接可能几分钟后就被静默断开表现为你切出去看了会儿网页回来发现终端死了。加上这三行之后连接能稳住几个小时不断。想确认某个主机最终生效的配置到底是什么用这个命令ssh -G dev-box它会把所有生效的配置项全部打印出来包括默认值。排查我明明在 config 里写了为什么不生效这类问题时特别好用——十有八九是因为匹配顺序问题config 里第一个匹配到的值生效后面的会被忽略。6.3 密钥生成、ssh-agent 和免密登录生成密钥ssh-keygen -t ed25519 -C meworkstation算法选 ed25519这是目前的主流推荐密钥短、速度快、安全性够。RSA 也能用如果非要 RSA 建议至少 3072 位ssh-keygen -t rsa -b 3072 -C meworkstation生成过程中问你要不要设置 passphrase。我的建议是设尤其是笔记本这种可能丢的设备。设了之后私钥被偷走也用不了会多一层保护。代价是每次用都要输一遍这就要靠 ssh-agent 来解决了。Windows 上的 ssh-agent 也是一个服务默认可能是禁用状态。启用它Set-Service -Name ssh-agent -StartupType Automatic Start-Service ssh-agent ssh-add $env:USERPROFILE\.ssh\id_ed25519加进去之后这次开机期间再连就不需要输 passphrase 了。注意ssh-add加进去的密钥在服务重启之后就没了所以如果你经常重启机器可能会觉得每次开机都要重新 add 很烦。这个是正常的从安全角度讲也是合理的——不加持久化密钥只在内存里。7. 常见故障排查这几个场景我踩过不止一次7.1 服务起不来报错五花八门服务启动失败是最常见的开局问题几种典型情况报错误 1067进程意外终止十有八九是配置文件语法错了。sshd 对配置文件格式很敏感多一个空格、少一个引号都会导致解析失败。诊断方法是用调试模式手工跑一遍cd C:\Program Files\OpenSSH .\sshd.exe -ddd -f C:\ProgramData\ssh\sshd_config-ddd是最高级别的调试输出它会把配置文件解析过程、主机密钥加载过程、绑定端口过程全都打出来哪一步出错一眼就能看到。注意这么跑的时候是前台运行会占住终端测试完 CtrlC 停掉就行。不要在服务已经跑着的时候再这么跑会因为端口被占用而失败那是正常的。报no hostkeys available -- exiting说明主机密钥丢了或者读不到。检查C:\ProgramData\ssh\下有没有ssh_host_*文件。没有的话手工生成命令见 4.3 节。有文件但读不到就是权限问题用 OpenSSHUtils 里的Repair-SshdHostKeyPermission修一下。服务能起但马上就退看事件日志是最快的路径Get-WinEvent -LogName OpenSSH/Operational -MaxEvents 20 | Format-Table TimeCreated, Id, LevelDisplayName, Message -AutoSize这个日志通道在服务端装好之后就是开启的里面记录了连接、认证、会话的所有关键事件。认证失败的记录尤其有用它会明确告诉你失败原因是密码错、密钥被拒、还是权限问题。7.2 能连上但登录被拒的几种情况连上 TCP 但登录被拒问题就集中在认证环节了。按这个顺序排查先确认账户名对不对。Windows 的账户名有时候带域名或者机器名前缀格式是机器名\用户名或者域\用户名。用whoami在目标机上确认真实格式SSH 里就照那个写。再确认密码。这个不用多说但要注意空密码账户默认是登不上的即使你在配置里开了密码认证也一样。然后就是前面反复提到的公钥路径和权限问题。这里给一个速查表现象最可能的原因处理方式一直提示输密码公钥无效管理员组用户密钥放错位置追加到administrators_authorized_keys密钥在正确位置但仍被拒ACL 里有多余的写权限主体用 icacls 重置继承并只授权 Administrators 和 SYSTEM公钥登录直接断开家目录或 .ssh 目录权限过松检查目录 ACL移除多余主体提示 too many authentication failures客户端一次性尝试了太多密钥在 config 里加IdentitiesOnly yes并指定 IdentityFile密码正确但提示拒绝访问账户被禁用或不在允许列表net user 用户名查看账户状态IdentitiesOnly yes这一条值得单独说。ssh-agent 里如果攒了七八个密钥客户端会把它们一个一个试过去很多服务端限制最多 6 次认证尝试还没轮到正确的那把就被踢了。加上这个配置强制只用指定的那把问题就消失了。7.3 三个 ssh.exe 打起来环境变量里的暗战这个坑挺隐蔽的但是中招之后特别迷惑。症状是你在 A 终端里跑 ssh 一切正常在 B 终端里跑同一个命令就报一些莫名其妙的错比如找不到 config、连不上特定主机、或者密钥加载失败。根因是机器上装了多份 SSH 实现。最常见的三个来源是系统自带的C:\Windows\System32\OpenSSH\ssh.exe、Git for Windows 附带的C:\Program Files\Git\usr\bin\ssh.exe、以及 WSL 或者 msys2 里的。它们的配置文件路径、默认算法策略、对某些参数的支持程度都不一样。诊断方法where.exe ssh Get-Command ssh -All | Select-Object Source把所有能搜到的列出来看顺序。PATH 里排前面的优先。如果发现用的是 Git 那个而不是系统的又想让某些场景用系统的两条路要么调整 PATH 顺序要么在所有地方都用绝对路径调用。这个问题在配 VS Code Remote-SSH 的时候特别容易撞上。VS Code 默认用 PATH 里的 ssh但它也提供了一个remote.SSH.path设置项可以显式指定用哪个 ssh.exe。遇到 Remote-SSH 连不上但命令行能连的情况第一件事就是去查这一项十有八九是指向了另一个 ssh。8. 上线之后加固与长期维护的几个习惯8.1 稳定运行一周后再做的四件加固新增的服务不要一上来就把安全策略拉到最紧那样出问题的时候你会连救火的路都没有。我的做法是先保证能用稳定跑一周再逐项加固每次改一项改完观察一天。四项加固按优先级排改端口。把 22 换成比如 2222 这种不常见的值。这个不是靠隐藏来防护而是把扫描器那种无差别扫全网 22 端口的噪声过滤掉日志能干净很多。改完记得同步改防火墙规则。关密码认证。前提是公钥登录已经全面验证通过而且你有别的通道RDP 或者第二个 SSH 会话能进去救火。改的方法是配置文件里把PasswordAuthentication设成 no。限制可登录用户。在配置文件里加AllowUsers或者DenyUsers把能登录的账户收敛到一个白名单里。默认情况下所有本地账户都能登录这对一台有二十个账户的服务器来说范围太大了。提高日志级别。把LogLevel从默认的INFO提到VERBOSE这样每次登录尝试的详细信息都会记录包括用了哪把密钥、从哪个 IP 来的。日志量会涨但对审计和事后追查很有价值。8.2 日志留存和审计的做法Windows 事件日志默认有大小限制OpenSSH/Operational这个通道默认好像只有 1MB 左右连接多的话几天就滚掉了。要长期留存得先把这个通道的容量调大wevtutil sl OpenSSH/Operational /ms:104857600/ms后面的单位是字节这个例子是 100MB。调大之后一般能用几个月。再长的话就得配日志转发把事件统一收集到一台日志服务器上但这个就属于更大范围的话题了单机场景下把容量调大基本够用。日常查看最近登录记录Get-WinEvent -LogName OpenSSH/Operational -MaxEvents 100 | Where-Object { $_.Message -match Accepted|Failed } | Select-Object TimeCreated, Message这条命令能筛出成功和失败的认证记录日常巡检看一眼就够了。8.3 升级和卸载别留尾巴升级这件事如果你走的是可选功能方式那跟着 Windows 更新走就行不用管。如果是 MSI 或者 zip 部署的就得自己维护。检查当前版本ssh -V sshd -V升级时先停服务替换文件再启动。注意配置文件在C:\ProgramData\ssh升级过程不会动它但主机密钥也在那个目录千万别在清理旧文件的时候顺手删了。删了的话所有客户端都会收到主机密钥变更警告很麻烦。卸载的话按安装方式对应处理Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0msiexec /x OpenSSH-Win64-vX.X.X.X.msi /quiet卸完之后C:\ProgramData\ssh这个目录不会自动删除里面还留着主机密钥、过去积累的 authorized_keys。如果不打算再装了手工清理掉如果只是暂时卸载留着也行重装之后能直接复用省得客户端重新确认指纹。另外记得把防火墙规则也删掉Remove-NetFirewallRule -Name OpenSSH-Server-In-TCP我个人在几台机器上跑 Windows OpenSSH 服务端已经两年多了最深的体会是这东西本身的稳定性非常好出问题的地方九成都不在 OpenSSH 身上而是卡在权限模型和路径细节上。管理员组那套独立的密钥路径机制、ACL 的继承规则、多份 ssh 互相干扰这三样基本覆盖了我遇到过的所有故障。把这些搞清楚之后剩下的就是常规的配置调优反而没什么好操心的了。
延伸阅读

更多相关文章

2026/10/1 19:17:12

从零搭建AI推理服务:环境、模型加载、批处理与性能观测实战

1. 从零搭建AI工程能力:为什么我劝你别急着调库 这两年AI应用开发的门槛肉眼可见地在降低,随便拉个框架、调几个API,一个能跑通的demo就出来了。但我自己带过几支团队、也面试过不少号称“做过AI项目”的候选人之后,发现一个很普遍…

2026/10/1 19:12:12

AI编程工业化:从开源模型到多Agent编队的工程实战

今天看到这条“今日AI大事件”时,我脑子里冒出的第一个词不是“融资”,也不是“大模型”,而是“工业化”。智谱一下子甩出50亿美元的消息,加上中国开源模型连续20周在排行榜上霸屏,再叠加AI编程开始讲“千人编队”&…

2026/10/1 19:12:12

GPT Image 2 API实战:从图像生成到局部编辑的自动化工作流

图像生成早就不停留在“出一张好看的图”阶段了。我最近把整套业务从纯生成改成“先生成、再局部编辑”的管线,核心驱动就是 GPT Image 2 API。这代 API 真正让人舒服的地方在于,它把生成和局部编辑统一成了同一个接口,既能用自然语言描述画面…

2026/10/1 21:22:20

卖家精灵 AI 评论分析 2.0:亚马逊评论分析维度、功能与使用场景

卖家精灵 AI 评论分析 2.0 面向亚马逊卖家,将大量、分散的 Amazon 评论整理为结构化、可追溯、可核验的消费者反馈。报告覆盖整体口碑、评价主题、使用情境、正负分歧、用户旅程、综合洞察和值得关注的反馈,并通过全局证据抽屉连接买家原话。单次最多分析…

2026/10/1 21:22:20

一句话生成代码:恐象AI,探索自然语言驱动的应用开发新模式

软件开发行业的发展,始终围绕降低开发门槛、提升交付效率两个方向演进。从早期机器语言、汇编语言,到高级编程语言,再到低代码、无代码平台,技术工具不断简化应用构建的操作流程。近年来,“一句话生成代码”成为AI应用…

2026/10/1 21:22:20

2026年汽配跨境B2B商城系统哪家好:车型适配比多语言更难做

2026年汽配跨境B2B商城系统哪家好:车型适配比多语言更难做做汽配出海的企业在选商城系统时,容易被"支持多语言多币种"这类通用能力打动。但汽配生意的真正难点不在这里——同一个零件在不同车型、不同年份、不同排量下有不同编号,原…

2026/10/1 21:22:20

不会设计也不套模板,怎么用 AI 快速做出一份能汇报的 PPT?

不会设计也不套模板,怎么用 AI 快速做出一份能汇报的 PPT?汇报要交PPT,自己不会设计,套模板又容易“内容和模板两张皮”。其实用AI做PPT的正确顺序,不是先找好看的模板,而是先理清汇报逻辑,再让…

2026/10/1 21:22:20

苏州售后完善的GEO优化服务商客户口碑力荐

Q1:如今采购方都习惯先问AI,如果AI回答里查不到自己的企业,该怎么办?这是当前制造业企业普遍遇到的难题。无论是机械装备、电子元器件、医疗器械还是建材、物流行业,采购负责人的第一站已经从搜索引擎搬到了AI对话框。他们习惯向…

2026/10/1 21:17:20

智能调度优化收官战报:异构算力装箱率提升 35% 的真实工程路径

智能调度优化收官战报:异构算力装箱率提升 35% 的真实工程路径在现代化算力中心中,GPU 硬件的昂贵程度无需多言。对于一家拥有数百台高性能 GPU 节点的企业而言,算力装箱率每提升 10%,就意味着每年可以节省数百万甚至上千万元的物…

2026/10/1 5:21:14

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/10/1 17:09:46

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 10:48:55

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑