ARTICLE DETAIL

资讯详情

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

Windows下SSH密钥免密登录全攻略:从密钥生成到多服务器配置

Windows下SSH密钥免密登录全攻略:从密钥生成到多服务器配置 1. 这一切是怎么开始的先讲个真实场景。我手上有七八台 Linux 服务器有的跑测试环境有的是线上业务的节点平时每周至少得登好几次。以前一直用的密码登录每次都要回忆那串大小写加符号的密码输错了还要重来。有一次脑子短路把密码里的#记成了数字键3连试四回被服务器锁了五分钟当天还被同事吐槽“怎么中午了服务还没起来”。后来我痛定思痛在 Windows 上把 SSH 密钥登录整套配完一次性把公钥推到了所有服务器上。从那之后终端里敲一条 ssh 命令就能直接进去再也没被密码折磨过。这篇文章就是把我这套流程完整写出来包括为什么这么做、每一步的坑在哪、以及多台服务器怎么批量管理。适合正在用 Windows 当主力开发机、又天天要连 Linux 服务器的朋友参考。说实话Windows 上做 SSH 密钥登录的教程不少但多数都只讲了“怎么生成密钥”“怎么传公钥”对 Windows 特有的权限问题、目录写法的坑、多主机配置文件怎么组织讲得很少。我这次会把细节一次性补齐让你照着操作就能落地。2. 先搞懂 SSH 密钥免密登录的原理2.1 为什么“一次配置”真的可行免密登录不是一个魔法。它的核心是非对称加密你本地生成一对密钥一个是私钥一个是公钥。私钥留在你自己的电脑上公钥部署到你想登录的目标服务器上。当你发起 SSH 连接时服务器会拿公钥去验证你的身份而验证过程中只有持有私钥的人才能通过挑战。用生活里的例子来类比公钥就像“锁芯”私钥就像“钥匙”。你把这把锁装到服务器门上你自己留着钥匙。服务器看到你来了就问你“能开我这把锁吗”你掏钥匙一拧锁开了身份就验过了。之后每次连接都不需要密码因为钥匙已经能打开那把锁了。所以“一次配置”的原理很简单私钥只有一份公钥可以复制分发到很多台服务器。只要每台服务器都装上了同一把“锁芯”你本地那一把“钥匙”就能开所有门。这也是这个标题里最核心的一个概念——公钥可以无限分发私钥永远不出本地。2.2 Windows 做这件事有什么特殊之处Linux 和 macOS 下的 OpenSSH 生态非常成熟命令也统一。但是 Windows 的 OpenSSH 是从系统组件层面集成进来的从 Windows 10 1809 和 Windows Server 2019 开始OpenSSH 客户端已经成为可选功能很多机器默认已经装好了。然而 Windows 至少有三个“坑”是教程里很少提到的第一没有原生的ssh-copy-id命令。Linux 上一条ssh-copy-id就能把公钥推到远程主机Windows 上要么手动用scp传要么先cat出来再拼接要么自己写脚本模拟。这就导致很多纯 Windows 用户第一次接触时摸不着头脑。第二路径写法和权限模型不同。Windows 下你的用户目录是C:\Users\你的用户名OpenSSH 默认读取的密钥路径是C:\Users\你的用户名\.ssh\id_ed25519。虽然新版本 OpenSSH 对 Windows 的权限检查没有 Linux 那么苛刻但如果你把.ssh目录设置成“Everyone 可写”它照样会拒绝认你的密钥。第三终端和代码工具共享密钥的路径不统一。在PowerShell里~/.ssh/能解析到用户目录在Git Bash里~/.ssh也能解析到同一个地方但在CMD里~可能就不一定好用。更尴尬的是如果你同时用VS Code Remote-SSH、WinSCP、PuTTY每个工具对密钥格式和私钥加载方式的理解都不一样。PuTTY 不认 OpenSSH 生成的私钥格式得先转换这个坑我后面也会提到。2.3 整体思路本地生成密钥仓库远程只有公钥在 Windows 上配置 SSH 免密登录的整体思路其实很清晰分四步走本地生成密钥对私钥留本地公钥拿出来。把公钥放到目标服务器~/.ssh/authorized_keys文件里。用 SSH 配置文件管理多台服务器避免每次敲完整用户和 IP。验证免密登录效果。后面所有内容都围绕这四步展开过程中穿插 Windows 特有的经验教训。3. Windows 环境准备与密钥生成3.1 检查 Windows 自带的 OpenSSH 客户端大部分新版 Windows 10/11 都已经自带 OpenSSH 客户端。你可以打开 PowerShell输入下面这行命令确认ssh -V如果输出了类似OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2的信息说明客户端已经完全可用了不需要再装额外的东西。如果提示“ssh 不是内部或外部命令”你需要手动去开启功能打开“设置 → 应用 → 可选功能 → 添加功能”然后找到OpenSSH 客户端安装即可。这个操作不需要重启装完重新打开终端就能用。我的建议是如果公司内网对软件安装权限管控很严优先用系统自带的 OpenSSH不要去装独立版的第三方 OpenSSH省得版本冲突。如果你经常在 Git Bash 里操作Git for Windows 里也自带一套 OpenSSH功能基本一样路径也指向用户目录。3.2 生成密钥ed25519 还是 RSA 4096密钥生成方法往下看。我推荐在 PowerShell 里执行ssh-keygen -t ed25519 -C 你的邮箱或备注如果你想要 RSA可以用ssh-keygen -t rsa -b 4096 -C 你的邮箱或备注关于选型我明确说我的结论优先用 ed25519。原因是它的密钥长度短、生成速度快、安全性强而且现代 OpenSSH 版本6.5 以上都支持。唯一的兼容性顾虑是极老的企业设备或老版本 Linux 发行版如果你要连的设备是五六年前的嵌入式系统或老旧 Unix 设备才需要考虑 RSA 4096 兜底。正常情况下ed25519 足够用。执行ssh-keygen后它会问你要保存路径。默认是C:\Users\你的用户名\.ssh\id_ed25519直接回车即可。然后它会要求设置 passphrase也就是私钥的额外口令。这一步我想多说一句passphrase 一定要设置但不用太长。它相当于给私钥加了一层保险。如果电脑被别人拿走没有 passphrase 你的私钥也打不开。每次 SSH 连接时它可能会提示输入 passphrase——这里有个技巧后面会讲到用 ssh-agent 来缓存它这样既安全又不烦人。但如果你实在不想每次输可以先留空后边再补。我个人强烈建议设置不要图一时方便。生成完成后~/.ssh目录下会有两个文件id_ed25519私钥绝对不能外传。id_ed25519.pub公钥可以分发到任意服务器。有的朋友会问能不能直接改文件名比如把私钥命名为my_key可以ssh-keygen会让你指定保存路径你指定成my_key即可。但这里有一个典型问题自定义文件名后SSH 默认不会自动加载连接时要么加-i参数指定私钥要么在配置文件中用IdentityFile明确指定。新手最好先用默认文件名等配置文件玩熟了再考虑多密钥管理。3.3 密钥权限检查与 Windows 的权限模型Linux 下如果.ssh目录权限过松SSH 会直接拒绝使用密钥。Windows 的 OpenSSH 也有权限检查但它基于 Windows 的 ACL而不是 Unix 的 600/700 权限位。Windows 端的常见问题是.ssh目录继承了用户目录的权限导致Everyone或者Authenticated Users有读权限。在 OpenSSH 的检测逻辑里如果私钥文件可以被其他用户读取它就会认为“私钥泄露风险”拒绝使用密钥。即使你是单机用户、不存在其他用户登录的可能性它也会按照这个逻辑停下来。解决方式有两种我推荐第一种方式一通过属性面板移除继承权限找到C:\Users\你的用户名\.ssh目录右键属性 → 安全 → 高级 → 禁用继承 → 将继承的权限转换为显式权限然后只保留你的用户账户为唯一所有者删除其他所有用户和组。对于id_ed25519私钥文件本身同样操作一遍只要你的账户可读取、可写入即可。方式二用 icacls 命令处理在管理员 PowerShell 里执行icacls $env:USERPROFILE\.ssh /inheritance:r icacls $env:USERPROFILE\.ssh\id_ed25519 /inheritance:r这两条命令的意思是移除.ssh目录和私钥文件的继承权限。执行完后再右键确认一下权限列表保留当前用户即可。我实测下来这比在图形界面里点来点去快很多。注意如果你用的是 Git Bash可能很多教程会直接告诉你chmod 600 ~/.ssh/id_ed25519。在 Git Bash 里这条命令对 Windows 的 ACL 有一定作用但效果不稳定。我建议无论如何都用 icacls 或图形界面把 ACL 设置干净这也是 Windows 下 SSH 免密登录最容易踩坑的地方。4. 把公钥部署到多台服务器4.1 单台服务器手动部署通用方法公钥部署的核心就是要把本地id_ed25519.pub文件里的内容追加到远程服务器用户主目录下的~/.ssh/authorized_keys文件里。这里给出一个在 PowerShell 里手动部署的万金油方法type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh root192.168.1.100 mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys这条命令的流程是用type命令读取本地公钥内容。通过管道传给远程 SSH 命令。远程命令依次执行创建.ssh目录如果不存在、设置目录权限 700、把收到的公钥内容追加到authorized_keys、把该文件权限改成 600。这里有个小细节为什么不用 scp 来传公钥因为 scp 单次只能传文件而且会覆盖目标文件。如果服务器上authorized_keys里已经有其他公钥你需要的是“追加”而不是“覆盖”。上面的思路是把公钥内容作为标准输入直接送到远程命令里天然就是追加语义。这也是为什么我推荐 PowerShell 管道方式而不是 scp 方式。如果你更喜欢把公钥先复制到远程再追加那第二步到远程主机上再执行cat id_ed25519.pub authorized_keys也是可以的只是多一步道理一样。4.2 快速跳过“首次连接确认”的技巧首次连接陌生服务器时SSH 会提示确认主机指纹The authenticity of host ... cant be established。手工输入yes没问题但如果你要写脚本批量推送公钥那每次都卡在这里很烦。解决方式是在 ssh 命令里加上-o StrictHostKeyCheckingno -o UserKnownHostsFile/dev/null注意这是一个很典型但有争议的做法。加上StrictHostKeyCheckingno可以跳过首次指纹确认UserKnownHostsFile/dev/null表示不把主机指纹写入 known_hosts 文件。好处是脚本不会中断坏处是有中间人攻击风险。如果你是在受控的内网环境批量初始化服务器临时用一下没问题。但在生产环境或者公网环境我不建议禁用指纹检查首次连接多一次确认是值得的。4.3 多台服务器的批量部署思路如果你要管理的服务器有十几台一台一台执行上面的命令也还是麻烦。我分享一个我常用的脚本思路先手动维护一个服务器清单文本文件servers.txt格式每行一条root192.168.1.101 deploy192.168.1.102 admin192.168.10.50然后在 PowerShell 里循环执行$pubKey Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub Get-Content servers.txt | ForEach-Object { $server $_ Write-Host 正在部署公钥到: $server $pubKey | ssh -o StrictHostKeyCheckingno $server mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys Write-Host 完成: $server }循环过程中第一次连接还会提示输入密码因为此时公钥还没有部署完。你需要逐个输入目标服务器的密码这是一次性成本。之后再次连接时所有服务器就都走密钥验证了。我自己用这个脚本批量部署过二十多台测试机大概花了十分钟其中大部分时间都在输密码。如果你觉得密码交互太烦可以考虑先把密码统一改成临时密码批量部署完再改回来。但在生产环境我不建议为了省事在脚本里明文记录密码这个习惯很危险。4.4 有没有更好的工具可以参考除了纯命令行你也可以在 Windows 上使用Termius或MobaXterm这类带 GUI 的 SSH 工具来做密钥管理。它们通常支持导入 OpenSSH 格式的私钥并在连接时自动加载。但我的建议是一定要先把原生 OpenSSH 的方式搞明白再考虑图形工具。原因是VS Code Remote-SSH、Git、rsync 这些工具底层都是用系统 OpenSSH 的配置和密钥来工作的。只要原生命令行跑通了其他工具全都能复用同一套密钥。如果你只在图形界面里配置了密钥VS Code Remote-SSH 可能还是找不到你的私钥到时候会更困惑。5. 用 SSH 配置文件实现“一次配置、多主机管理”5.1 配置文件到底能解决什么问题公钥部署完免密登录已经生效了。但你会发现每次连接还是很啰嗦比如要敲ssh -i C:\Users\你的用户名\.ssh\id_ed25519 deploy192.168.1.102 -p 22022主机多起来之后IP 记不清、端口记不清、用户名也记不清。OpenSSH 提供了一个强大的配置文件~/.ssh/config。你可以给每一台服务器起一个别名把连接参数都写好之后只需要ssh 别名就能连上。这就是标题里“一次配置”的完整形态密钥只生成一次、公钥分发到所有目标服务器而每个服务器的 IP、端口、用户名差异全部由本机配置文件统一管理。5.2 config 文件的标准写法和常用参数打开C:\Users\你的用户名\.ssh\config如果没有这个文件就新建一个无需扩展名然后按下面的格式写Host web-prod HostName 192.168.1.101 User deploy Port 22 IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60 ServerAliveCountMax 3 Host db-backup HostName 192.168.1.102 User root Port 22022 IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60 Host bastion HostName bastion.example.com User admin Port 2222 IdentityFile ~/.ssh/id_ed25519 ProxyJump jump-server常用的参数我整理如下Host别名可以自定义。连接时用ssh web-prod代替长命令。HostName目标主机的 IP 或域名。User登录用户名。PortSSH 端口默认为 22。IdentityFile指定使用哪个私钥文件。ServerAliveInterval每隔多少秒向服务器发送保活包防止长时间无操作被断开。ServerAliveCountMax连续多少次保活包未响应才断开连接。ProxyJump如果要从跳板机中转可以在这里指定跳板机别名非常方便。这里有一个最容易被忽略的细节HashKnownHosts和HostKeyAlgorithms不要轻易动。你在网上可能看到过一些教程建议加HostKeyAlgorithmsssh-rsa来兼容老服务器我当时为了连一台老设备也这么干过。其实这是在 Older OpenSSH 版本禁止 ssh-rsa 算法的场景下的临时缓解方案。如果你的服务器不是特别老不要全局加这种配置否则等于把加密算法降级了有安全风险。5.3 通配符与多主机批量规则如果你的服务器很多而且命名有规律你可以用通配符来减少配置重复。比如Host *.internal User deploy IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60 Host web-* User www Port 22但这里有个重要规则SSH 读取配置文件时匹配规则是按顺序从上到下每个参数取第一次匹配到的值。也就是说如果你在Host *里设了User root后面专为某台机器再设置User deploy后者能不能生效取决于匹配顺序和参数覆盖逻辑。在 SSH 配置里同一个参数如果出现在多个匹配的 Host 段中取第一个匹配到的值。所以通用参数放在文件末尾、特殊参数放在文件前面的顺序安排是有讲究的不是随便排的。我踩过的坑是这样的当时我给所有生产服务器统一配置了User root又给其中一台特殊机器配置了User deploy结果连着连着发现ssh special-server还是以 root 登录。后来查资料才明白原理调整了块顺序才解决。所以请你记住越具体的配置放前面越通用的配置放后面。5.4 其他 Windows 工具怎么复用同一套密钥配置好 Windows 原生 OpenSSH 之后其他工具天然就能复用前提是你做对了以下两点第一VS Code Remote-SSH。VS Code 默认使用系统的 OpenSSH 客户端它会读取~/.ssh/config。你只要在远程资源管理器里添加主机时直接填别名比如web-prod它就能自动读取对应的 HostName、User 和 IdentityFile。以前我一度以为 VS Code 有自己的独立配置后来发现完全复用省了很多事。第二Git。如果你用 Git 拉取 GitHub 或公司 GitLab 的代码可以把 GitHub 的私钥加进~/.ssh/config并给github.com专门设置一个Host条目。例如Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github这样你既可以用同一个.ssh目录管理所有密钥也可以在 Git 操作中自动选择正确的私钥。如果连 GitHub 还需要配代理也在这段配置里设置ProxyCommand或ProxyJump但这一步涉及网络环境具体情况按你自己的网络条件来。6. 常见问题、权限坑与故障排查实录6.1 为什么密钥看着没问题还是提示要密码遇到这种情况百分之八十是远程服务器上的authorized_keys文件权限或路径不对。先排查目录结构在远程主机上执行ls -la ~/.ssh/正常情况下应当看到authorized_keys文件并且.ssh目录权限是 700authorized_keys文件权限是 600。如果你看到的是 755 或 644用下面命令修正chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys再有一个容易忽略的点如果你登录的是 root 用户有些系统会通过sshd_config里的PermitRootLogin参数限制 root 使用密钥登录。如果普通用户可以免密但 root 不行去服务器上检查/etc/ssh/sshd_config里的配置PermitRootLogin prohibit-passwordprohibit-password意味着禁止纯密码登录但允许密钥登录。很多云主机默认是yes或prohibit-password你需要确认它没有设置为no。改完配置记得重启 sshd 服务systemctl restart sshd提示修改 sshd 配置前最好开一个持久连接的终端窗口如果改错导致 SSH 断掉你还能通过其他方式回滚。6.2 Bad owner or permissions 怎么处理这是 Windows 上点击率很高的一个报错完整提示类似 WARNING: UNPROTECTED PRIVATE KEY FILE! Permissions for C:\\Users\\xxx\\.ssh\\id_ed25519 are too open.原因就是我前面提到的 Windows ACL 权限问题。解决办法就是用 icacls 移除继承权限icacls $env:USERPROFILE\.ssh /inheritance:r icacls $env:USERPROFILE\.ssh\id_ed25519 /inheritance:r执行完再连接一次如果还有问题把id_ed25519文件的 ACL 手动设置成只允许当前用户完全控制。右键文件 → 属性 → 安全 → 编辑删掉无关用户只保留你的账户。这一条我建议所有 Windows SSH 用户都提前操作一遍不要等到报错了再处理。尤其是从旧电脑迁移过来的.ssh目录或者公司域控环境下继承权限特别复杂的机器最容易出这个问题。6.3 服务器公钥没生效连不上提示 Permission denied如果公钥已经追加到authorized_keys但连接仍然提示Permission denied (publickey,password)按下面顺序排查第一步检查服务器端是否开启了公钥认证grep PubkeyAuthentication /etc/ssh/sshd_config如果没有显式配置默认是开启的。但如果你之前有人改过把它设成了no那就无法走密钥登录。第二步用详细日志模式连接看看到底是哪一步失败了ssh -v userserver日志里如果出现Offering public key说明客户端尝试提供密钥如果出现Authentications that can continue: publickey,password说明服务器拒绝如果出现No more authentication methods to try说明没有可用认证方式了。第三步检查你的本机是否真的用了正确的私钥。如果本地同时有多个私钥比如id_ed25519、id_rsa、id_ecdsaSSH 会依次尝试但目标服务器的authorized_keys里只有其中一个公钥。你可以在ssh -v日志里看到它尝试了哪些密钥路径确认是否匹配。6.4 配置了 config 文件还是连接失败出现这种情况多数不是密钥问题而是配置文件里的参数冲突。举个例子你给Host *配了User root但给某个别名配了User admin结果 SSH 匹配顺序取到了第一个值还是用 root 登录密码当然不对。排查方法很简单在 PowerShell 里运行ssh -G 别名-G参数会输出该主机名的实际生效配置。如果这个命令显示出来的user和你预期不一致那就说明你配置文件里的 Host 块顺序或者覆盖逻辑有问题对照着调整即可。这个ssh -G命令是排查配置文件的利器但我发现很多朋友不知道它存在。它可以把别名对应的最终参数全部打印出来连接之前就能看到你实际用的是哪个 IP、哪个用户、哪个私钥非常直观。6.5 Windows 下 ssh-agent 的问题如果你使用了 passphrase 保护私钥会发现每次连接都要输一次 passphrase。虽然免了服务器密码但本地还是要输口令很烦。解决办法是启用 ssh-agent 服务让它在内存中缓存你解锁后的私钥。在 Windows 上OpenSSH Authentication Agent 服务默认可能没启动。执行以下命令查看状态Get-Service ssh-agent如果没启动把它设为自动启动并运行Set-Service ssh-agent -StartupType Automatic Start-Service ssh-agent然后添加私钥到 agentssh-add $env:USERPROFILE\.ssh\id_ed25519添加时会提示输入一次 passphrase之后在同一会话里连接其他服务器就不用再输了。重启电脑后 agent 重置需要重新执行ssh-add。这里我遇到过一个很坑的情况公司电脑用域账户登录ssh-agent 服务老是自动停止。找了一圈原因发现是组策略限制了服务的“允许服务与桌面交互”选项。如果你也碰到 agent 服务明明设了自动却总是停止可以先用管理员权限手动启动实测能解决大多数问题。另外如果你用的是 Git Bash它自带了一个代理机制但和 Windows 的 ssh-agent 是两个不同的东西。我的建议是统一用 Windows 的 ssh-agent因为 VS Code Remote-SSH 走的是 Windows OpenSSH不会认 Git Bash 的配置。6.6 一台服务器换了 IP 或端口配置怎么更新服务器迁移或者 IP 变了之后不要慌张。你只需要改本地~/.ssh/config文件里的HostName和Port参数即可私钥和公钥完全不用动因为服务器身份验证主要看密钥对跟 IP 没有绑定关系。但需要注意旧 IP 的主机指纹可能已经记录在known_hosts文件里。如果你连接新 IP 时提示REMOTE HOST IDENTIFICATION HAS CHANGED那是因为服务器指纹和你本机记录的不一致。此时需要先清理旧记录ssh-keygen -R 旧IP清理完再重新连接接受新的指纹即可。这个指令不改变私钥和公钥只清指纹记录。6.7 常见问题速查表现象可能原因解决思路提示公钥文件权限过宽.ssh目录或私钥文件 ACL 继承过多用户用 icacls 移除继承权限只保留当前用户公钥已传但还是要密码远程authorized_keys权限不对或目录不存在远程执行 chmod 700/600 并确认文件内容连接时没有尝试密钥本地私钥路径或别名配置不对用ssh -G 别名查看生效参数多台服务器个别能连个别不能目标服务器authorized_keys内容不对确认公钥是否完整、是否误覆盖每次连接都要输入 passphrasessh-agent 未启动或未添加私钥启动 Agent 服务并执行 ssh-addKnown hosts指纹冲突服务器 IP 更换或重装系统用 ssh-keygen -R 清理旧指纹远程 root 无法密钥登录sshd_config 中限制 root 登录方式检查PermitRootLogin并重启 sshdVS Code Remote-SSH 认不出别名config 文件路径未被识别确认~/.ssh/config位于用户主目录下7. 密钥日常管理与安全加固经验7.1 私钥备份与迁移私钥只有一份万一电脑硬盘坏了所有服务器的免密登录就废了。我建议把私钥备份到加密的 U 盘或密码管理器里但备份的私钥本身一定要加密最好单独设置一个强 passphrase。公钥丢了无所谓重新生成再分发就行私钥千万不能弄丢。迁移到新电脑时把.ssh整个目录复制过去注意保持目录结构完整。复制后第一件事就是去检查权限新电脑上目录的文件 ACL 通常会是默认继承状态极大概率触发UNPROTECTED PRIVATE KEY FILE的报错按前文命令清一遍继承权限就生效了。如果你备份私钥用的是密码管理器要注意一点OpenSSH 私钥是文本格式很多密码管理器可以存文本但建议把私钥文件作为一个附件存进去不要直接粘贴到笔记里。防止别人通过笔记软件的云同步把私钥泄露出去。7.2 不要把私钥提交到 Git 仓库这是我见过翻车率最高的安全问题.ssh目录意外被 Git 仓库包含然后推到 GitHub 或公司 GitLab。哪怕仓库是私有的也不该把私钥放进去因为任何有权访问仓库的人都能拿到你的私钥。解决方案是一劳永逸地加上全局忽略规则。在 Git 全局配置里设置 ignore 文件或者直接在.gitignore里写.ssh/ *.pem id_*更安全的做法是把.ssh目录放在用户主目录下且尽量不要把一个项目的 Git 仓库根目录放在用户主目录本身。如果你目前用的开发目录正好覆盖了.ssh赶紧把仓库移走。7.3 定期轮换密钥密钥用了三年五年理论上没问题但安全习惯上还是建议定期轮换比如一年一次。轮换的步骤很简单本地生成一组新密钥。把新公钥追加到服务器authorized_keys中。验证新密钥可以正常登录。从authorized_keys中移除旧公钥。本地更新config文件中的IdentityFile路径。这样整个过程不需要停服务器也不需要让用户重新注册平滑过渡。我通常是每半年检查一次看服务器上authorized_keys文件内容及时清理掉离职同事或旧电脑遗留的公钥。7.4 建议服务器上关闭密码登录等你把密钥登录在所有服务器上都验证成功后可以考虑关闭密码登录只保留密钥登录。这是 Linux 服务器安全加固里非常基础的一环。编辑/etc/ssh/sshd_configPasswordAuthentication no PubkeyAuthentication yes然后重启 sshd。改完就意味着没有你私钥的人连输入密码的机会都没有。这对防止暴力破解非常有效。但做这一步之前你务必要确认自己能用密钥登录到所有账户并且本地密钥是完好的。我有一个血的教训有一次我在一台远程主机上改完配置重启 sshd结果发现本地连接时私钥路径错了我直接把自己锁在外面最后是通过云厂商控制台的 VNC 才把配置改回来。所以我的建议是改配置之前先开一个保持不动的终端确认密钥登录成功后再修改配置并重启。万一把自己锁了还有一个备用终端可以救急。7.5 多密钥多场景的分层管理如果你既要连公司服务器、又要连个人 VPS、还要用 GitHub/GitLab建议不要所有地方都用同一把私钥。而是分场景生成不同密钥通过 config 文件来路由。我的分配方式是这样的id_ed25519_personal个人 VPS 和家庭服务器。id_ed25519_company公司内网服务器和公司 GitLab。id_ed25519_githubGitHub 专用。config 文件里通过不同的Host条目指定不同IdentityFile再配合Host github.com User git这样的写法Git 操作自然就按场景走。这种做法的好处是一旦某一组密钥泄露你可以单独吊销那一组不需要把所有服务器的公钥全换掉。坏处是管理复杂度稍微高一点但只要你 config 文件组织得清晰问题不大。8. 我对这套流程的一些体会如果只让我总结一句的话我会说这条路的真正门槛不在命令而在 Windows 的权限管理和配置文件逻辑。命令就那么几条网上到处都能搜到但Bad owner or permissions、config 覆盖顺序、ssh-agent 自动停止这类问题不踩几次坑是真的想不明白。我在实践中最受益的一个习惯是把~/.ssh目录视为一个“密钥保险箱”来管理。目录里只放私钥、公钥、config 和 known_hosts。不去手动改私钥文件内容不让第三方工具擅自改权限每次新装工具后都先跑一遍ssh -G确认配置没被破坏。这样坚持半年下来几乎没再遇到过莫名其妙的连接报错。这篇文章写到最后再送你一个实用小技巧如果你平时要在多台 Windows 机器之间切换可以把.ssh/config和公钥文件放到自己的同步盘里私钥不要放同步盘而是用 U 盘拷贝。迁移新电脑时先拷config再手动 Copy 私钥然后顺手执行一遍 icacls。这一套流程下来新机器从零到免密登录所有服务器不会超过二十分钟。
返回列表