Windows下SSH密钥登录配置全攻略:从生成到部署

发布时间:2026/10/20 22:26:33
Windows下SSH密钥登录配置全攻略:从生成到部署 1. 为什么 Windows 用户必须把 SSH 密钥登录用起来说实话很多 Windows 用户在很长一段时间里对 SSH 这玩意儿的心态都是能不碰就不碰。早年间 Windows 自带的是 Telnet 客户端想用 SSH 还得装 PuTTY、Xshell 这些第三方工具不够省心。后来虽然系统自带 OpenSSH 了但不少人还是习惯于打开终端敲一条ssh userip然后老老实实输密码。问题是密码登录这套东西在生产环境里真的是越来越不好用了。我之前在某个内部项目里管过一小批 Linux 服务器团队里几位同事使用密码登录结果密码泄露之后被扫了一遍日志里全是爆破尝试的记录。后来彻底切到密钥登录耳根子才清净下来。这篇文章要聊的就是纯 Windows 环境下怎么把 SSH 密钥登录从零到一完整地跑通。内容包括密钥生成、公钥部署、ssh-agent 配置、config 文件写法以及我实际踩过的一些权限和路径相关的坑。适合正在从密码登录往密钥登录迁移的个人开发者、运维新手以及想在 Windows 上把 SSH 体验做得更顺手的朋友。在 Windows 上做这件事有几个跟 Linux/macOS 很不一样的地方比如密钥文件的权限管理更麻烦、ssh-agent 默认不是自动启动的、路径写法经常混用反斜杠等。这些要是没人提醒第一次搞很容易卡住。2. 密钥生成这一步选对算法和参数比什么都重要2.1 Windows 自带 OpenSSH 客户端别再装第三方的了先确认一下环境。Windows 10 1809 之后的版本、Windows 11 全系列系统里都内置了 OpenSSH 客户端。不需要装 PuTTY也不需要另外装 Git Bash 才能用。打开 PowerShell敲下面的命令看看版本ssh -V正常会输出类似OpenSSH_for_Windows_9.5p1这样的信息。如果提示无法识别或者未找到那就去设置 - 应用 - 可选功能里添加OpenSSH 客户端。提示Windows 自带的 OpenSSH 是微软编译维护的版本跟 Linux 发行版里的 OpenSSH 用法一致这里说的一致是指命令行参数、配置文件格式、密钥格式没区别配置文件路径稍有不同后面会讲到。2.2 ed25519 优先为什么不是 RSA生成密钥的命令本身很简单ssh-keygen -t ed25519 -C your_emailexample.com -f $HOME\.ssh\id_ed25519这里建议优先选 ed25519。原因很简单密钥短、生成快、安全性在当前主流认知里比 2048 位的 RSA 更强而且 OpenSSH 7.0 以后对它的支持已经非常成熟了。RSA 不是说不能用但到了 3072 位甚至 4096 位之后密钥文件很长看着费劲而且如果服务器端 OpenSSH 版本较老可能会遇到一些兼容性限制。ed25519 密钥就三百多字节干净利落。对于老旧的服务器——比如 OpenSSH 版本低于 6.5 的那种——才需要考虑 RSA 或者 ECDSA。不过这种古董级别的服务器本身就应该更新了不建议为它委曲求全。2.3 passphrase 到底要不要设置执行上面那条命令后会提示输入 passphrase。很多教程会说直接回车就好我个人的建议是本地开发机可以不设公司配发的电脑或者需要长期保留私钥的机器一定要设。passphrase 的作用不是加密传输过程而是加密私钥文件本体。即使有人拷走了你的私钥文件没有 passphrase他也无法使用。代价是每次用 SSH 时都要输一次或者在 ssh-agent 里输入一次。Windows 上设置 passphrase 之后配合后面要讲的 ssh-agent体验其实不差——开机后往 agent 里手动添加一次密钥后面整个会话周期内都不需要再输入。如果一开始没设 passphrase事后想补也是可以的ssh-keygen -p -f $HOME\.ssh\id_ed25519这条命令会引导你输入旧 passphrase空的直接回车再设置新的。3. 公钥部署Windows 上没有 ssh-copy-id但你有一百种替代办法3.1 手动追加 authorized_keys密钥生成之后$HOME\.ssh\目录下会多出两个文件id_ed25519私钥留在本地永远不要发给任何人id_ed25519.pub公钥需要放到服务器的~/.ssh/authorized_keys文件里Linux 和 macOS 上有现成的ssh-copy-id命令一条命令就能把公钥推到服务器上。Windows 自带的 OpenSSH 没有这个命令所以要手动操作。先说标准做法。假设你要登录的用户是deploy服务器 IP 是192.168.1.100你需要做两件事第一步在 Windows 上查看公钥内容cat $HOME\.ssh\id_ed25519.pub第二步用一个已经能登录的账号去服务器把公钥追加到目标用户目录下mkdir -p ~/.ssh chmod 700 ~/.ssh echo ssh-ed25519 AAAA...your-public-key... your_emailexample.com ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys这段命令是在服务器上执行的不是在 Windows 上执行。注意authorized_keys文件如果不存在用重定向会自动创建。但如果已经存在再执行同样的命令就会追加一行不会覆盖原有内容。这一点比直接把文件传上去要安全不容易把已有密钥弄丢。3.2 用 PowerShell 实现 ssh-copy-id 的效果每次手动敲命令有点烦尤其是一台新服务器开出来或者是给团队成员批量部署公钥的时候。我在实际中会临时写一个 PowerShell 函数来模拟 ssh-copy-id 的行为function Add-SshPublicKey([string]$RemoteUser, [string]$RemoteHost, [string]$KeyPath $HOME\.ssh\id_ed25519.pub) { $key Get-Content $KeyPath $remoteCommand mkdir -p ~/.ssh chmod 700 ~/.ssh echo $key ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys echo DEPLOYED_OK ssh $RemoteUser$RemoteHost $remoteCommand }用的时候一行搞定Add-SshPublicKey deploy 192.168.1.100这个函数会要求你输入一次密码之后同一台服务器再登录就不需要密码了。3.3 服务器端是否允许密钥登录先自查一下公钥部署好了但连接时仍然提示输入密码这种情况很常见。核心原因多半是服务器的 sshd 配置有问题或者文件权限不对。当你用密码登录进服务器后可以顺手看一下这几个点~/.ssh目录权限必须是 700不能是 777其他组用户可写也会出问题~/.ssh/authorized_keys权限必须是 600 或 644不能是 666/etc/ssh/sshd_config里PubkeyAuthentication必须是yes服务器如果开启了 SELinux还要确认相关策略没有拦截 SSH 读 authorized_keysWindows 上如果登录不上还有一个隐蔽问题有些人在 Windows 上打开authorized_keys文件编辑结果换行符被存成 Windows 格式CRLF服务器端解析时就容易懵。解决办法是编辑时用 VS Code、Notepad 这类工具明确把行尾改成 LF。4. 拍平 Windows 上密钥文件的权限问题4.1 为什么 Windows 的 .ssh 目录权限容易被搞乱这是整个 Windows SSH 配置里最容易被忽视的一条。在 Linux 上chmod 700 ~/.ssh一条命令就完事。但 Windows 上的 OpenSSH 对权限检查非常严格如果~/.ssh目录或私钥文件让 Everyone 或者普通 Users 组拥有了读取权限它可能会直接拒绝使用这个私钥。症状是这样的私钥明明存在路径也对配置文件的写法也对但连接时就是报 WARNING: UNPROTECTED PRIVATE KEY FILE! 原因通常是目录被其他用户继承到了不必要的权限。比如你把.ssh目录放在某个共享目录下或者某些同步工具OneDrive、坚果云之类的把权限搞乱了。4.2 用 icacls 手工收权查一下当前权限icacls $HOME\.ssh一般会看到类似这样的输出表示当前用户有完全控制权限但可能还有Everyone或Authenticated Users的条目C:\Users\yourname\.ssh NT AUTHORITY\SYSTEM:(I)(F) yourname:(I)(F) BUILTIN\Administrators:(I)(F)处理办法是给当前用户重置为完全控制同时删掉其他用户的权限icacls $HOME\.ssh /inheritance:r icacls $HOME\.ssh /grant:r $($env:USERNAME):F对私钥文件也做同样处理icacls $HOME\.ssh\id_ed25519 /inheritance:r icacls $HOME\.ssh\id_ed25519 /grant:r $($env:USERNAME):F执行完毕后再执行ssh命令时那个警告一般就会消失。4.3 新版 Windows OpenSSH 的 NTAuthenticationPrincipal 处理另有一种情况比上面的更隐蔽。有些版本的 Windows OpenSSH 在ssh-keygen生成密钥后会在密钥文件上额外写入一个特殊的 ACL 条目跟某个 SID 关联。正常情况下没有影响但如果你用某些工具批量改过用户配置文件可能出现私钥能读但被拒的诡异状态。这时候最干脆的办法是删掉重新生成一份密钥然后立刻用icacls收紧权限。生成之后默认权限一般就是可用的不用多折腾但如果中间经过第三方软件复制粘贴权限就容易被弄坏用上面的命令收一遍更稳妥。5. ssh-agent 与 config 文件让 Windows 上的 SSH 体验真正舒坦起来5.1 开启 OpenSSH Authentication Agent 服务默认情况下Windows 的 ssh-agent 服务是手动启动状态甚至直接是禁用。这就导致你每次打开终端用 SSH 时如果私钥设了 passphrase都要重新输一次。在 PowerShell管理员模式下执行Get-Service ssh-agent | Set-Service -StartupType Automatic Start-Service ssh-agent然后确认一下状态Get-Service ssh-agent输出里Status是RunningStartType是Automatic就算配置好了。把密钥添加到 agentssh-add $HOME\.ssh\id_ed25519如果私钥有 passphrase这一步会要求输入一次。之后这个会话周期内再连服务器就不再需要重复输入了。注意Windows 的 ssh-agent 有一个小毛病——它只在用户登录会话里有效开机后如果从没打开过任何终端agent 是在服务列表里挂着但实际密钥仓库是空的。也就是说每次重启之后第一次使用前都要手动跑一次ssh-add。目前没有特别完美的开机自动解锁方案除非用 DPAPI 之类的机制写脚本把 passphrase 存在凭据管理器里但那样做也有安全副作用我不太推荐在生产环境里这么搞。有一个替代思路如果嫌麻烦可以把私钥 passphrase 去掉。风险是私钥文件一旦泄露别人直接用。折中方案是给私钥一个较复杂的 passphrase同时只在每次解锁后保留 agent 会话期间你离开电脑时锁定 Windows 或干脆注销就安全很多。5.2 config 文件把主机别名、端口、密钥路径全部固化Windows 上 OpenSSH 的全局用户配置文件在C:\Users\你的用户名\.ssh\config如果文件不存在可以新建一个没有扩展名。我用的是这个模板Host myserver HostName 192.168.1.100 User deploy Port 2222 IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 30 ServerAliveCountMax 3 Host jump-host HostName 10.0.0.5 User ops IdentityFile ~/.ssh/id_ed25519_jump配置好之后连接服务器只需要ssh myserver不用再记用户名、IP、端口那一串东西。日志里如果经常断连ServerAliveInterval 30这个参数会每 30 秒发一个 keepalive 包很有用。5.3 在 config 里配置代理跳板机团队内部网络常见的场景一台跳板机在公网几台内网服务器只允许跳板机或者特定网段访问。如果不做任何配置从 Windows 直连内网机器当然是不通的。正确姿势是在 config 里加一段Host internal-server HostName 192.168.10.8 User admin ProxyJump jump-host然后连接ssh internal-server命令会自动先连到跳板机再从跳板机跳到目标机器。跟手动两步 ssh 的区别在于ProxyJump 是在本地 ssh 进程里建立连接转发的私钥在本机完成认证不会在不安全的位置留下转发的 agent socket。这个用法对 Windows 用户来说非常友好。6. 微信小程序里常见的报错与解决完全用得上这里面的逻辑我遇到过一个挺有意思的场景某个内部工具需要小程序的开发环境主动连某个服务器结果大家全在 Windows 上一个人在改配置另一个人就登不上了。其实最终的排查逻辑还是回到密钥登录的几个要点上。下面把 Windows 上最高频的几个 SSH 密钥登录问题整理成一张对照表症状常见原因排查顺序提示Permission denied (publickey)公钥没部署到正确位置或 sshd 没开启 PubkeyAuthentication先看服务器日志再确认 authorized_keys 是否存在内容是否匹配提示UNPROTECTED PRIVATE KEY FILE.ssh 目录或私钥权限过宽用 icacls 收权连接后提示密码密钥不生效公钥格式不对或 authorized_keys 换行符是 CRLF用编辑器另存为 LF有效密钥但连不上agent 里也没有没有写 IdentityFile 到 config 文件检查 config 文件路径和文件名输入 passphrase 后连接中断ssh-agent 服务异常看看 ssh-agent 状态重启服务6.1 日志怎么查Windows 上排查 SSH 客户端问题加-v参数是最快的路径ssh -v myserver输出会显示每一步读哪个 config、加载哪个 IdentityFile、发送公钥给服务器、服务器是否接受。如果看到Offering public key: ...之后没有任何后续重点检查服务器端的authorized_keys内容。服务器端日志在/var/log/auth.logDebian/Ubuntu或/var/log/secureRHEL/CentOS。看到Failed publickey for deploy就说明公钥本身没匹配上。6.2 sshd_config 里容易踩的坑在 Windows 上维护 Linux 服务器时最麻烦的就是有些服务器只改了sshd_config里的PasswordAuthentication no却忘了重启 sshd结果新的设置根本没生效。排查这类问题一个很可能是坑的操作是改完配置后直接关闭连接然后重连就会发现已经进不去了。因为你在修改过程中如果断开了当前连接而新配置里已经禁了密码登录同时公钥又没配好那就只能去机房或远程管理卡里处理了。建议的流程是先用ssh -o PubkeyAuthenticationyes deployserver测试公钥登录是否正常。确认没问题再改sshd_config里的PasswordAuthentication no改完不要急着断线再开一个终端窗口测试连接。确保万无一失后再关掉旧窗口。6.3 密钥轮换的实操节奏生产环境里定期轮换密钥是基本功。Windows 上管理多把私钥时我的习惯是每把私钥都映射到一个具体用途服务器 A 用一把构建机用一把不要一把私钥走天下在.ssh/config里为每个 Host 指定不同的 IdentityFile轮换时先向服务器追加新公钥再用新私钥登录验证验证通过后再从 authorized_keys 中移除旧公钥这样做的好处是万一某把私钥泄露影响面可以控制不用把几十台机器上的 authorized_keys 全部重写一遍。Windows 上还应该特别注意私钥文件不要放到漫游配置文件里。因为漫游配置文件会在多台设备间同步等于是把私钥复制得到处都是。如果是个人电脑确保私钥只在当前机器上存在如果是公司电脑建议确认 IT 策略没有把用户目录下的 .ssh 给自动同步掉。7. 从密码登录切换到密钥登录迁移过程中的安全和兼容性考量7.1 别急着关掉密码登录前面讲了很多密钥登录的好处但实际操作中全公司所有服务器马上全部禁用密码登录这种激进做法我个人不建议。理由有三点很多老旧的自动化脚本、定时任务、计划任务还在用密码或者密码环境变量连 SSH一刀切了这些任务会立刻崩团队成员如果在 Windows 上密钥有问题一旦密码登录被禁就只能等着维护窗口才能进服务器审计要求有时需要保留某些账号的密码登录能力以配合堡垒机或跳板机策略稳妥的步骤是先给所有目标用户部署公钥保持密码登录和密钥登录同时可用观察两到四周看有没有人反馈密钥登不上确认稳定后把服务器PasswordAuthentication no保留一个应急账号可以从某些特殊网段用密码登录以备不时之需7.2 多台服务器批量部署公钥Windows 上写个简单的 PowerShell 脚本可以循环把公钥推到多台机器。前提是你要有这些机器的密码或者已经有密钥登录权限。脚本我不贴完整代码了套路很简单写一个数组存所有机器 IP循环调用前面那个Add-SshPublicKey每台机器第一次都会要求输密码。需要注意的是循环操作时如果中途某台机器密码错误脚本会卡住所以要加一个-BatchMode yes或者用sshpass之类的工具在 Linux 上配合但 Windows 上没有现成方案。我的做法是挨个来一台一台确认别图快。7.3 密钥备份与恢复密钥丢了比密码忘了还麻烦。密码忘了可以找管理员重置私钥丢了如果服务器上只有这一把公钥那就只能通过其他管理通道进服务器改 authorized_keys 了。所以建议在生成密钥时就单独备份一份私钥到一个加密压缩包里。Windows 上可以用系统自带的 BitLocker 加密 U 盘或者用 7-Zip 配合一个高强度密码加密整个.ssh目录。备份是必要的但也要注意存到网盘、企业协作目录、甚至 Git 仓库里都是错误操作。私钥文件外泄一次就相当于把密码明文贴在服务器上。7.4 多密钥并存时的 IdentityFile 配置细节如果一台机器有多把私钥比如一把用于个人 Git 仓库、一把用于工作环境、一把用于服务器管理OpenSSH 的默认行为是逐个尝试加载的。如果默认尝试的顺序不对会出现密钥对不上但系统还在尝试下一把的情况连接速度会很慢甚至因为尝试次数过多被服务器 ban。正确做法是在 config 里用IdentitiesOnly yes明确指定只尝试某个 IdentityFileHost personal-git HostName git.example.com User git IdentityFile ~/.ssh/id_ed25519_personal IdentitiesOnly yes Host work-git HostName git.corp.example User git IdentityFile ~/.ssh/id_ed25519_work IdentitiesOnly yes这样每次连接都会直接使用指定的私钥不会拿着错误的私钥去试探服务器。8. 连接速度优化与 Windows 终端里的细节补充8.1 连接慢的问题Windows 下 SSH 连接偶尔会出现输完命令后卡住好几秒才出密码提示的情况。常见原因是 DNS 反向解析超时以及 IPv6 探测失败。在 config 里加上这段能明显改善Host * GSSAPIAuthentication no ConnectTimeout 5GSSAPIAuthentication no在 Windows 上默认通常已经是 no但有些企业域环境里会被打开如果当前网络没有对应的 Kerberos 服务开启状态下会导致连接等待很久才超时。8.2 用 WSL 还是在 PowerShell 里跑一个经常被问的问题Windows 上直接用 OpenSSH 客户端还是通过 WSL 里的 ssh我的看法是如果你只是需要连接服务器、跑命令、传文件用系统自带的 OpenSSH 就够省略掉一层虚拟化。Windows 自带的 OpenSSH 性能上没有问题而且在 PowerShell 里跑scp、sftp也很顺手。如果你需要用到一些只有 Linux 生态才有的工具比如脚本依赖 bash 特性、要用ssh-copy-id那装个 WSL 在前面做跳板更自然。两种方式下的.ssh/config文件即使路径不同写法是一致的有没有 WSL 不影响这篇文章介绍的核心操作。8.3 终端自动加载 ssh-agent 的小技巧虽然前面说了开机后要手动ssh-add但我找到一个稍微省事的做法在 PowerShell profile 里加一段判断如果 agent 列表为空就自动尝试加载默认私钥。# $PROFILE 指向的文件里追加 if (-not (ssh-add -L 2$null)) { ssh-add $HOME\.ssh\id_ed25519 2$null }这样每次打开新终端时如果检测到 agent 是空的且默认私钥存在就会自动添加。首次会要求输入 passphrase之后同个终端会话内不需要再输入。9. 我实际用下来的几个经验总结做最后分享密钥登录这件事配置过程本身不难真正麻烦的是排查那些 Windows 特有的权限问题和服务自动启动问题。我的建议是先在本地虚拟机上完整走一遍流程确认每一步的行为再往生产环境推。有些人在 Windows 上配置完毕自我感觉良好结果第二天开机发现服务没起来、密钥也没加载连接直接失败很容易带来挫败感。几个你可以直接复用的要点生成密钥用ssh-keygen -t ed25519别再用古老的 RSA 1024Windows 下.ssh目录的权限如果报错用icacls比改用任何图形化工具都可靠ssh-agent服务一定要设成开机自启不然每次重启后都得手动改多台服务器统一管理时把 config 文件写全User、Port、IdentityFile、IdentitiesOnly都放进去以后才不慌关密码登录前先测试密钥能登录再改配置最后重启 sshd另外想提醒一点密钥登录不是万能的。如果你在 Windows 上自己管理私钥却不小心把私钥同步到了某个公开位置那等于把门钥匙挂在门口。最好定期检查一下.ssh目录下到底有哪些文件尤其是.pub和私钥是否都各就各位。如果你也在 Windows 上折腾 SSH希望这篇里的细节能帮你少走几步弯路。尤其是 icacls 那段我印象太深了——当初因为权限问题折腾了两天最后发现只是复制粘贴时把 ACL 弄坏了。这种问题在 Linux 上一个chmod就解决了在 Windows 上多花点时间搞清楚icacls后面就一马平川了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询