尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Windows部署OpenSSH服务端实战:从解压到公钥登录

Windows部署OpenSSH服务端实战:从解压到公钥登录 简介面向 Windows 用户的 OpenSSH 64 位离线安装包解决 Windows 平台缺少原生 SSH 工具、难以安全远程登录和传输文件的问题适合系统管理员、开发者在命令行或 PowerShell 中部署 SSH 服务也适用于本地开发、服务器运维、内网设备管理等场景。压缩包共 29 个文件以 13 个可执行程序为核心另有 4 个 PowerShell 脚本、2 个 JSON 配置、2 个说明文档及 DLL 运行库整体仅 4.86MB轻量且结构清晰。内含 SSH 客户端、服务端、安全复制与文件传输组件附带安装与卸载脚本、默认配置示例、密钥管理及权限修复模块可用于启用 SSH 服务、远程执行命令、加密传输文件并在部署完成后处理目录权限、主机密钥等易错环节。当前已有 800 人学习下载适合需要在 Windows 上快速搭建 SSH 环境、减少第三方图形界面依赖的技术用户收藏备用也适合作为内网离线部署时的基础组件。1. OpenSSH-Win64.zip 能做什么给 Windows 服务器补上可携带的 SSH 服务端OpenSSH-Win64.zip 看起来只是一个普通的 64 位压缩包但很多 Windows 运维手里都会留一份。原因很简单Windows 10 之后系统自带 OpenSSH 客户端服务端也能通过“可选功能”装上可一旦你到了内网 Windows Server、虚拟化宿主机或离线测试环境会发现在线安装不一定可用版本也不可控。这个 zip 包是微软维护的 Win64 版 OpenSSH 绿色二进制包解压、运行一个脚本、放行防火墙就能把一台 Windows 机器变成 SSH 服务端同一包里的 ssh.exe、scp.exe 也能做客户端工具。适合需要版本锁定、离线分发、快速给多台 Windows 服务器开 SSH 通道的人。下文按我实际落地时的顺序讲清楚每一步。2. 解压与安装把 Win64 压缩包变成能开机自启的 sshd 服务很多人看到 openSSH-Win64.zip 就觉得“解压即用”实际这是第一个误区。zip 包里的 sshd.exe 能运行和能作为 Windows 服务开机自启、能被外部连进来中间还差着三步解压到正确的目录、跑安装脚本注册服务、放行防火墙。不夸张地说我见过一半的失败都发生在“没跑 install-sshd.ps1”上。我一般会把目标路径固定在C:\Program Files\OpenSSH而不是C:\OpenSSH或桌面。原因有两个一是 Program Files 下的 NTFS 权限默认给 SYSTEM 和 Administrators 足够访问权sshd 服务以 SYSTEM 身份运行时不会突然没权限二是这个路径是社区脚本和文档里最常用的默认路径以后出问题对着博客、事件日志排查路径对得上的概率高很多。如果你非要放别的路径也不是不行但后面手工配置服务时要格外小心。2.1 先拆包确认 sshd.exe、sftp-server.exe 和脚本是否齐全解压不要用资源管理器拖到桌面再移动那样容易把文件 ACL 弄乱。常见做法是先用 PowerShell 解压到临时目录再把内容拷贝到目标路径顺便检查包内是否有一个多余的顶层目录。代码块如下# 把 zip 解压到临时目录避免直接写入 Program Files 失败 $tmp C:\temp\openssh_unzip $zip D:\archives\OpenSSH-Win64.zip Expand-Archive -Path $zip -DestinationPath $tmp -Force # 查看临时目录里的文件层次确认 exe 是不是直接在这一层 Get-ChildItem $tmp -Recurse -Name如果Get-ChildItem列出的文件里没有 sshd.exe说明 zip 内还有一层目录你需要把那一层的内容整体拷到最终路径。我常用这条命令处理多一层目录的情况# 将临时目录中的所有文件拷贝到 C:\Program Files\OpenSSH Copy-Item -Path $tmp\* -Destination C:\Program Files\OpenSSH -Recurse -Force拷贝完成后确认关键文件是否齐全。install-sshd.ps1 和 sshd.exe 缺一不可前者负责服务注册后者是 sshd 服务本体。还要顺便确认有没有sftp-server.exe因为后面的 SFTP 子系统要依赖它。cd C:\Program Files\OpenSSH Get-ChildItem -Name ssh.exe, sshd.exe, sftp-server.exe, install-sshd.ps1逻辑说明Expand-Archive -Force会在目录已存在时覆盖同名文件但不会清理多余文件所以如果之前装的版本残留了旧文件建议先Remove-Item -Recurse -Force清掉旧目录再解压。Copy-Item -Recurse -Force把目录原样复制避免漏掉子目录里的配置文件。参数-Force在这里的意义是覆盖旧文件不弹出交互确认。提示Win64 包只能装在 64 位 Windows 上。在 32 位系统上强装会直接提示“不是有效的 Win32 应用程序”这不是命令写错了而是架构不匹配。2.2 用管理员 PowerShell 跑通 install-sshd.ps1 的最小命令文件齐了之后真正的服务安装步骤其实很短。注意前提PowerShell 必须以管理员身份运行否则脚本创建服务会收到“拒绝访问”。最小命令组如下# 管理员 PowerShell 中执行 Set-Location C:\Program Files\OpenSSH powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\install-sshd.ps1 # 注册成功后检查服务 Get-Service sshd执行完第一段install-sshd.ps1 通常会做两件事生成主机密钥并把 sshd 注册成名为sshd的 Windows 服务。这里有个很常见的坑脚本被系统执行策略拦住报错xxx.ps1 cannot be loaded because running scripts is disabled on this system。上面我用了-ExecutionPolicy Bypass它只对当前这一条命令生效不会修改系统全局执行策略是相对安全的绕法。如果Get-Service sshd能返回服务但状态是Stopped不要慌继续做两步# 设置开机自启并立即启动 Set-Service -Name sshd -StartupType Automatic Start-Service sshd Get-Service sshdSet-Service -StartupType Automatic把启动类型改成自动否则服务器重启后 sshd 不会自动跑起来这是远程连不上的经典原因之一。Start-Service立即启动不需要等重启。如果Get-Service sshd直接报“找不到服务”说明脚本没成功检查输出的错误信息。常见的是脚本运行时路径不对或者当前 PowerShell 不是管理员。还有一种特殊情况机器上已经通过“可选功能”装过 OpenSSH Server服务名同样是sshd。此时 zip 包里的 install-sshd.ps1 可能不会覆盖现有服务需要用以下命令先停掉旧服务再重新安装。这条命令务必要看清用户和会话不要在一台正在对外提供服务的机器上乱删。# 如果已经有旧的 sshd 服务先停掉并删除 Stop-Service sshd sc.exe delete sshd Set-Location C:\Program Files\OpenSSH powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\install-sshd.ps1sc.exe delete sshd是删除服务。注意sc.exe对参数格式极度敏感delete后面不能有任何多余的空格交换。如果依赖 install-sshd.ps1 不成功手动用sc.exe create sshd binPath C:\Program Files\OpenSSH\sshd.exe start auto也能注册服务但这条命令里等号后的空格一格都不能少属于 Windows 服务命令的经典“玄学”。我一般不会优先用手工方式因为脚本还会顺带生成主机密钥手工注册还要额外跑ssh-keygen.exe -A。2.3 防火墙、自启、服务依赖三个默认动作缺一不可服务跑起来后先做本地验证在看防火墙之前用Test-NetConnection -ComputerName 127.0.0.1 -Port 22看 22 端口通不通。如果本地通外部不通问题基本出在防火墙或安全组。Windows 防火墙默认拦截所有入站端口所以必须给 sshd 放行 TCP 22。我常用这组命令# 先查一下是否已经存在同名规则避免重复创建 Get-NetFirewallRule -Name OpenSSH-Server-In-TCP -ErrorAction SilentlyContinue # 没有同名规则就新建放行 TCP 22 入站 New-NetFirewallRule -Name OpenSSH-Server-In-TCP -DisplayName OpenSSH Server (sshd) -Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow -Enabled True参数说明-Direction Inbound表示入站规则-Protocol TCP限制为 TCP-LocalPort 22是 SSH 默认端口如果你在第 3 章把 sshd_config 里的Port改成了 2222这里必须同步改。-Enabled True让规则立即生效。-ErrorAction SilentlyContinue用来忽略“查询不到规则”的报错看起来像没反应但那是预期行为。如果服务器在云环境或机房有硬件防火墙Windows 防火墙放行还不够还要去安全组、网络策略里放行对应端口。很多“装了 OpenSSH 却连不上”的问题Windows 这边已经绿灯其实是外层安全组没有放行。这个问题在云服务器上尤其常见别只盯着 Windows 里看。在 2.2 里设置了自动启动但还有一层依赖要注意sshd 服务依赖 TCP/IP 协议栈。如果系统启动顺序异常服务会因依赖没就绪而启动失败。常见做法是把服务启动类型设成自动后再用sc.exe qc sshd看一眼服务的依赖项列表。如果DEPENDENCIES里已经写明了Tcpip就不用管如果为空也可以手工加上sc.exe config sshd depend Tcpip。这一步不是每个环境都需要但如果你反复遇到“开机后 sshd 没起来”值得查一下。到这里OpenSSH-Win64.zip 已经变成了一台能监听 22 端口的 Windows 服务器。下一步才是真正决定能不能登进去的关键配置 sshd_config。3. 配置 sshd_configWindows 上端口、登录限制与 authorized_keys 的落地参数安装脚本跑通之后真正决定远程体验的是C:\ProgramData\ssh\sshd_config。注意路径不是解压目录里的那份。install-sshd.ps1 会把一份默认配置复制到 ProgramData 下sshd 服务启动时优先读这一份。如果你直接改 zip 包解压目录里的文件大概率会发现“改了没反应”因为服务根本没读它。3.1 先找到 C:\ProgramData\ssh\sshd_config再改这五个字段打开配置文件之前先备份一份这是最后的后悔药。改配置锁死自己这种事在 SSH 领域太常见了密码登录关掉、公钥又没配置好最后只能本地登录去改文件。备份命令Copy-Item C:\ProgramData\ssh\sshd_config C:\ProgramData\ssh\sshd_config.bakWindows OpenSSH 的配置指令和 Linux 版大体兼容但要注意没有 root 概念所以不要写PermitRootLogin那是 Linux 参数Windows 上要么被忽略要么在启动时给语法错误。常见需要改的字段如下# C:\ProgramData\ssh\sshd_config 中常用到的配置 Port 22 ListenAddress 0.0.0.0 PubkeyAuthentication yes PasswordAuthentication yes MaxAuthTries 3 LoginGraceTime 30 ClientAliveInterval 300 ClientAliveCountMax 2 LogLevel VERBOSE AllowUsers admin10.1.0.0/16 Subsystem sftp C:\Program Files\OpenSSH\sftp-server.exe参数说明Port服务端监听端口。改成非 22 可以减少扫描噪音但排气时别忘同步防火墙规则。内网环境下我一般保留 22减少自己忘改防火墙的失误。ListenAddress默认监听所有网卡。如果你只想让某个内网 IP 提供 SSH 服务写成ListenAddress 192.168.1.20这里用具体 IP不是 0.0.0.0。PubkeyAuthentication公钥认证开关必须yes才能用 authorized_keys 免密登录。PasswordAuthentication是否允许密码登录。刚部署时建议先保持yes等公钥确认能登录后再关掉否则容易把自己锁在外面。MaxAuthTries单次连接里最多允许的认证尝试次数。默认是 6建议压到 3减少爆破面。LoginGraceTime从建立连接到完成认证的超时时间默认 120 秒改成 30 秒可以防挂机占连接。ClientAliveInterval与ClientAliveCountMax应用层心跳。服务器每 300 秒向客户端发一次存活包连续 2 次没应答就断开适合清理网络掉线的僵尸会话。LogLevel排障时开VERBOSE平时建议回INFO否则事件日志刷得很快。AllowUsers格式为用户名来源地址支持 CIDR比如AllowUsers admin10.1.0.0/16表示只允许 admin 从 10.1.0.0/16 网段登录。Subsystem sftpSFTP 子系统路径。路径含空格时一定要用双引号包起来否则 sshd 解析时会把C:\Program当成可执行文件sftp 服务直接起不来。改完配置文件后必须重启 sshd 服务才生效Restart-Service sshd Get-Service sshd如果重启后服务状态变成Stopped大概率是配置语法有硬伤。这时不要慌先去事件查看器看OpenSSH/Operational日志里面会记录具体的配置错误行。回滚也很简单把之前备份的sshd_config.bak拷回去再重启服务。3.2 公钥登录在 Windows 上的权限要求icacls 与 authorized_keysLinux 上我们习惯往~/.ssh/authorized_keys里塞公钥就跑通Windows 上没那么简单。默认路径是C:\Users\用户名\.ssh\authorized_keys而且 OpenSSH 对文件权限极度敏感如果该文件继承了太多用户权限sshd 会认为文件不够安全直接忽略它表现为“公钥配置了仍然要输密码”。我自己踩过好几次这个坑症状非常诡异公钥内容完全正确服务端日志也显示找到了公钥但始终认证失败。原因就是 authorized_keys 从父目录继承了 Users 组的写权限。Windows 上必须用 icacls 把权限收干净只保留当前用户和 SYSTEM# 在目标 Windows 服务器上执行admin 替换成实际用户名 icacls C:\Users\admin\.ssh\authorized_keys /inheritance:r icacls C:\Users\admin\.ssh\authorized_keys /grant:r admin:F icacls C:\Users\admin\.ssh\authorized_keys /grant:r SYSTEM:F命令含义/inheritance:r表示移除所有继承的权限/grant:r表示替换该用户的权限:F是完全控制。这里没有给 Administrators 组留权限因为在很多默认 Windows 环境里管理员组也不该随意改这个文件。如果用户名带域名或计算机名前缀比如DOMAIN\admin需要写成DOMAIN\admin:F并用引号包住否则反斜杠会被命令行吃掉。如果.ssh目录本身不存在scp 推送公钥之前要先创建。直接在远程 shell 里执行ssh admin192.168.1.20 if not exist C:\Users\admin\.ssh mkdir C:\Users\admin\.ssh注意authorized_keys 文件最好通过 scp / type 追加生成不要用记事本手动转存。记事本默认可能带 UTF-8 BOMOpenSSH 解析第一行公钥时会读到 BOM 字符导致第一把公钥永远验证失败。3.3 用 MaxAuthTries、LoginGraceTime 和 AllowUsers 收紧登录入口很多内网 Windows 服务器第一次开 SSH 时都是裸奔状态默认配置太宽松。我把常用的几个参数列成对照表方便你直接照抄参数默认值推荐值作用MaxAuthTries63限制单次连接尝试密码次数LoginGraceTime12030认证超时超时自动断连ClientAliveInterval0300应用层心跳间隔秒ClientAliveCountMax32心跳连续无响应多少次后断开表中前两个参数是防爆破的关键。MaxAuthTries 3不是说最多只能试三次密码而是单次连接内最多尝试三次超过后断开攻击者需要重新建立连接这会显著拖慢爆破速度。LoginGraceTime 30配合使用会自动清理那些连上来又不认证的连接。AllowUsers是比防火墙更贴近业务的访问控制。比如只允许admin从内网管理网段登录其他用户一律拒绝AllowUsers admin10.1.0.0/16 ops10.2.0.0/24也可以反过来用DenyUsers排除个别账号。Windows 账户名不区分大小写但配置里建议保持和 whoami 输出一致减少误判。如果AllowUsers写错或来源 IP 不匹配用户会看到“Permission denied”而不是密码提示这是正常的。改这些参数前先备份配置改完立即Restart-Service sshd再开一个新窗口测试登录不要把自己现在这个会话断开否则配置错了连回来救的机会都没有。4. 客户端接入用 OpenSSH-Win64.zip 里的 ssh.exe 免密登录 Windows服务端配好之后客户端反而容易翻车。原因很现实Windows 10 之后系统自带C:\Windows\System32\OpenSSH\ssh.exe你自己解压的 OpenSSH-Win64.zip 里也有一份ssh.exe两边版本不同容易让人分不清到底在用谁。我后面会讲怎么排但先按正确思路把客户端流程走一遍。4.1 生成 ed25519 密钥对而不是默认 RSA 的一个理由现在生成新密钥我的首选不是 RSA而是 ed25519。默认 RSA 是 3072 位安全性没问题但密钥长度长、生成慢而且对用户来说很难判断位长够不够。ed25519 密钥固定短、算法速度快在 Windows OpenSSH 的新版本里支持得很好和 Win64 包配合使用最省心。生成命令如下# 在客户端机器上生成 ed25519 密钥对输出到当前用户的 .ssh 目录 ssh-keygen -t ed25519 -a 64 -C office-adminwindows-ssh -f $env:USERPROFILE\.ssh\id_ed25519参数说明-t ed25519指定密钥类型-a 64设置 KDF 迭代次数值越大暴力破解私钥越难64 是相对保守的选择-C是注释通常写用途和用户名-f指定私钥保存路径公钥会自动生成在同目录下的.pub文件。执行后会提示输入 passphrase。如果这是个人测试环境、经常需要脚本自动登录可以直接回车跳过如果是生产环境建议至少设置一个 passphrase然后把私钥加载到 ssh-agent 里这样日常使用不用每次输入。加载方式是# 把私钥加入当前用户的 ssh-agent 服务 ssh-add $env:USERPROFILE\.ssh\id_ed25519如果提示无法连接 agent先在管理员 PowerShell 里把 ssh-agent 服务设为自动并启动Set-Service -Name ssh-agent -StartupType Automatic Start-Service ssh-agent4.2 用 ~/.ssh/config 给 Windows 主机起短名Host、User、IdentityFile 写法机器一多每次敲ssh admin192.168.1.20 -i C:\Users\admin\.ssh\id_ed25519非常累。常见做法是在客户端创建C:\Users\用户名\.ssh\config文件把主机信息固化下来。# C:\Users\用户名\.ssh\config Host win-srv HostName 192.168.1.20 User admin IdentityFile ~/.ssh/id_ed25519 StrictHostKeyChecking accept-new字段说明Host是自定义短名后面连接直接ssh win-srvHostName可以写 IP 或 DNS 名User是登录 Windows 的目标账户不加域名时就是本机账号IdentityFile指定私钥路径这里~会被 OpenSSH 自动展开成当前用户目录StrictHostKeyChecking accept-new表示只在第一次遇到新主机时自动接受主机指纹避免交互卡住同时不会像no那样完全关闭校验。如果有多台同网段机器还可以用通配符共享参数Host 192.168.1.* User admin IdentityFile ~/.ssh/id_ed25519这样连接ssh 192.168.1.21也会自动使用 admin 用户和指定密钥。注意 config 文件对格式较敏感缩进用空格没关系但拼写不能错。改完后用ssh win-srv测试如果还是提示密码先检查-v输出里是否加载了你指定的 IdentityFile。4.3 用 scp 与一条远程命令把公钥安全地写进 authorized_keysWindows 上没有 Linux 里现成的ssh-copy-id我一般用两步替代先 scp 把公钥推到远程临时文件再 ssh 远程执行追加命令。这是最不会破坏换行符的做法。完整顺序如下# 第 1 步确保远程 .ssh 目录存在 ssh admin192.168.1.20 if not exist C:\Users\admin\.ssh mkdir C:\Users\admin\.ssh # 第 2 步把公钥推到临时文件 scp $env:USERPROFILE\.ssh\id_ed25519.pub admin192.168.1.20:C:/Users/admin/.ssh/authorized_keys_tmp # 第 3 步追加到 authorized_keys删临时文件并收紧权限 ssh admin192.168.1.20 type C:\Users\admin\.ssh\authorized_keys_tmp C:\Users\admin\.ssh\authorized_keys del C:\Users\admin\.ssh\authorized_keys_tmp icacls C:\Users\admin\.ssh\authorized_keys /inheritance:r icacls C:\Users\admin\.ssh\authorized_keys /grant:r admin:F逻辑说明第 1 步中的远程命令由 Windows OpenSSH 默认的 cmd.exe 解释if not exist是 cmd 语法不能写成 Linux 的mkdir -p。第 2 步的 scp 目标路径我写成了C:/Users/admin/.ssh/authorized_keys_tmp正斜杠在 OpenSSH 里兼容性更好反斜杠容易转义出错。第 3 步用连接了四条远程命令type ... ...把公钥追加到 authorized_keysdel删除临时文件两条icacls收紧文件权限。这一步做完用户才真正具备公钥登录条件。如果远程用户的 shell 被改成了 PowerShell连接符会失效需要把第 3 步改成 PowerShell 语法但默认情况很少遇到。另一种更稳的做法是把公钥直接推到C:/Users/admin/.ssh/authorized_keys不要先推临时文件这样会把原文件覆盖所以只适合首次配置。配置完后在客户端执行ssh win-srv whoami如果能看到win-srv\admin输出说明公钥链路已经通了。此时回到服务端把 sshd_config 里的PasswordAuthentication改成no才是一台真正只接受密钥登录的 Windows SSH 服务器。5. 避坑手册OpenSSH 服务装上后连不上的五个高频原因这部分算是我多年来在 Windows 下接 SSH 的血泪经验。很多问题看起来是玄学实际上是几个固定环节没做对。我会按“现象 → 原因 → 解决”的顺序写方便你直接对照。5.1 Connection refused服务没启动先看 22 端口有没有在听现象客户端执行ssh admin192.168.1.20立刻提示Connection refused。这是最直接的“端口没在监听”信号。原因sshd 服务没有运行或者监听的端口不是 22。也有可能是防火墙直接丢弃但“refused”比 timeout 更偏向本地端口没通。解决先看服务状态和端口监听。在服务器本地管理员 PowerShell 执行Get-Service sshd Get-NetTCPConnection -LocalPort 22 -ErrorAction SilentlyContinue | Select-Object LocalAddress, LocalPort, State第一行确认服务是否是Running第二行确认 22 端口是否有进程在 Listen。如果服务是Stopped执行Start-Service sshd再查一次。如果端口没有输出多半是 sshd 启动失败去事件查看器看OpenSSH/Operational日志里面有具体报错。如果端口显示 Listen 但外部仍 refused检查 Windows 防火墙规则是否作用在错误的网络配置文件上比如机器当前网络是“公用”而你只放行了“专用”。5.2 密码正确仍被拒sshd 日志里没有细节时去事件查看器找线索现象窗口弹出密码输入密码肯定是对的但连续几次都被拒。服务端没有明显日志像是停在“黑匣子”里。原因常见有三类。一是 sshd_config 里PasswordAuthentication no已经关掉了密码认证二是AllowUsers或DenyUsers把来源 IP 或用户挡掉了三是 Windows 账户密码为空OpenSSH 默认拒绝空密码账户登录。解决把LogLevel临时设成VERBOSE重启服务再触发一次登录然后看事件日志Get-WinEvent -LogName OpenSSH/Operational -MaxEvents 30 | Select-Object -ExpandProperty Message如果日志里出现Failed none或authentication methods相关描述说明认证方式不匹配如果是user ... not allowed说明 AllowUsers 过滤生效。改配置前先备份确认原因后回退即可。5.3 命令行 ssh.exe 版本和 zip 包里的不是同一个现象你明明把新 OpenSSH-Win64.zip 解压到了C:\Program Files\OpenSSH但执行ssh -V看到的版本号还是旧版或者连接时出现算法不支持的报错。原因Windows 自带了一个ssh.exe路径是C:\Windows\System32\OpenSSH\ssh.exe并且这个目录通常在 PATH 的前面。你输入的 ssh实际跑的是系统自带版本不是 zip 包里的版本。解决用Get-Command ssh看实际路径确认到底调的是哪一个。如果确实想用 zip 包里的新版本把解压目录插到 PATH 最前面# 把 OpenSSH 目录放到 PATH 最前对当前会话生效 $env:Path C:\Program Files\OpenSSH; $env:Path ssh -V注意不要覆盖 System32 里的 ssh.exe系统更新会把那个文件恢复原样。如果你在写自动化脚本直接使用绝对路径C:\Program Files\OpenSSH\ssh.exe更稳妥少踩 PATH 的坑。5.4 修改 sshd_config 后重启服务但不生效配置行被注释或路径不对现象把Port改成 2222重启服务后用Test-NetConnection localhost -Port 2222一看端口不通再看 22 端口还是开着。感觉配置没被读取。原因大概率改错了文件。sshd 服务读的是C:\ProgramData\ssh\sshd_config你如果改的是解压目录C:\Program Files\OpenSSH\sshd_config自然不生效。另一种情况是配置行被放在文件末尾但前面多了注释符或者指令名拼写不对sshd 把整行当无效配置忽略了。解决先确认服务实际使用哪个配置文件。用sc.exe qc sshd查看服务的BIN_PATH确认 sshd.exe 位置再打开C:\ProgramData\ssh\sshd_config检查内容。修改后必须重启Restart-Service sshd Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue | Where-Object { $_.LocalPort -in 22,2222 } | Select-Object LocalAddress, LocalPort, State如果 22 和 2222 同时出现在监听列表里说明旧服务进程没有正确退出或者有两个 sshd 实例。检查是否有多个服务、多个 sshd.exe 在跑。5.5 公钥放对了位置仍要输入密码文件和目录权限没有收紧现象authorized_keys 文件内容明明和公钥一模一样但登录时仍然提示输入密码。原因这是 Windows OpenSSH 特有的权限检查在起作用。文件继承了 Users 组的写权限或者当前用户不是文件的所有者sshd 会拒绝信任该公钥文件。另有可能是文件保存成了带 BOM 的 UTF-8第一行公钥头部混入 BOM 字符。解决在服务器上重新收紧文件权限icacls C:\Users\admin\.ssh\authorized_keys /inheritance:r icacls C:\Users\admin\.ssh\authorized_keys /grant:r admin:F icacls C:\Users\admin\.ssh\authorized_keys /grant:r SYSTEM:F执行完后再用客户端加-v连接观察输出是否有Offering public key以及Authentication succeeded。如果仍然密码登录继续检查.ssh目录本身是否也带继承权限。目录建议用同样方式处理icacls C:\Users\admin\.ssh /inheritance:r icacls C:\Users\admin\.ssh /grant:r admin:F icacls C:\Users\admin\.ssh /grant:r SYSTEM:F处理完权限后重启一次 sshd再用公钥登录。绝大多数“公钥放对仍要密码”的案例到这里都能解决。6. 进阶与验证把 OpenSSH-Win64 做成内网批量部署模板6.1 一键部署脚本里的执行顺序为什么这么重要如果只有一两台机器手动敲命令没问题但如果你要维护几十台 Windows Server就需要把第 2 章的步骤固化成脚本。这里顺序很重要先解压再注册服务再设自启最后放行防火墙。顺序反了会出现“防火墙规则已建但服务还没注册成功”的假象。下面是一个最小可用的模板# 内网批量部署 OpenSSH 服务的脚本骨架 $dest C:\Program Files\OpenSSH Set-Location $dest # 1. 注册服务并生成主机密钥 powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\install-sshd.ps1 # 2. 自启并启动 Set-Service -Name sshd -StartupType Automatic Start-Service sshd # 3. 放行防火墙 New-NetFirewallRule -Name OpenSSH-Server-In-TCP -DisplayName OpenSSH Server (sshd) -Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow -Enabled True脚本里的-ExecutionPolicy Bypass只影响当前命令不会污染系统策略。批量推送时建议先把 zip 包解压到文件服务器共享目录再用psexec或计划任务在各节点执行上面的脚本。6.2 用一行命令验证服务、端口和登录链路部署完不能只看服务状态要连登录链路一起验证。我习惯用三条命令组合# 验证服务状态 Get-Service sshd | Select-Object Status, StartType # 验证端口监听 Test-NetConnection -ComputerName 127.0.0.1 -Port 22 # 验证真实登录链路用绝对路径的 ssh.exe 避免命中系统自带版 C:\Program Files\OpenSSH\ssh.exe -o StrictHostKeyCheckingno -o ConnectTimeout5 adminlocalhost echo ssh-okTest-NetConnection返回的TcpTestSucceeded为 True 只代表端口能握手不代表能登录所以最后一条命令才是关键。它能一次性验证服务端配置、用户权限、公钥链路和远程 shell 是否正常。我自己的习惯是把固定版本的 OpenSSH-Win64.zip 留存一份放在内部文件服务器上任何新装 Windows Server 都从那里拷贝绝不在每台机器上乱升版本哪怕只是临时开通道也一定跑 install-sshd.ps1因为手工造服务很容易漏掉主机密钥生成这一步。如果哪天不小心把配置改坏了别急着重装先看事件日志再回头比对我这篇模板里的顺序问题通常就是某一环节漏了。希望帮到你。本文还有配套的精品资源点击获取
返回列表