告别‘Permission denied’在Ubuntu 22.04上为Gerrit配置Ed25519 SSH密钥的完整流程含~/.ssh/config优化如果你最近在Ubuntu 22.04上使用Gerrit时遇到了Permission denied (publickey)的错误别担心——这很可能是因为你的SSH密钥类型与最新安全标准不兼容。随着OpenSSH 8.8及更高版本默认禁用传统的RSA签名算法许多开发者突然发现他们长期使用的SSH密钥不再有效。本文将带你一步步解决这个问题从生成更安全的Ed25519密钥对开始到优化你的SSH配置确保你的Gerrit访问既安全又稳定。1. 为什么你的SSH密钥突然失效了最近几年网络安全领域发生了重大变化。OpenSSH 8.8Ubuntu 22.04默认安装的版本出于安全考虑默认禁用了使用SHA-1哈希算法的RSA签名。这不是一个bug而是一个安全特性——SHA-1算法已被证明存在漏洞可能被恶意利用。当你看到类似下面的错误信息时debug1: Offering public key: /home/user/.ssh/id_rsa RSA SHA256:... agent debug1: send_pubkey_test: no mutual signature algorithm这表明你的客户端和服务器无法就一个双方都支持的签名算法达成一致。虽然服务器可能仍然接受RSA密钥但你的客户端OpenSSH 8.8已经拒绝使用不安全的签名方式发送它们。为什么Ed25519是更好的选择更强的安全性Ed25519使用椭圆曲线密码学比传统RSA更抗量子计算攻击更小的密钥尺寸一个安全的Ed25519密钥只需256位而同等安全的RSA密钥需要3072位更快的签名验证Ed25519操作比RSA快得多被现代系统广泛支持包括Gerrit在内的所有主流Git服务器都支持Ed255192. 生成Ed25519密钥对让我们从生成一个新的Ed25519密钥对开始。打开终端输入以下命令ssh-keygen -t ed25519 -C your_emailexample.com系统会提示你选择保存密钥的位置默认是~/.ssh/id_ed25519和设置密码。我强烈建议接受默认位置这样SSH客户端能自动找到它设置一个强密码来保护你的私钥使用ssh-agent来管理你的密钥密码避免频繁输入生成完成后你会得到两个文件~/.ssh/id_ed25519你的私钥绝不要分享这个~/.ssh/id_ed25519.pub你的公钥这就是你要添加到Gerrit的验证密钥生成是否成功ls -l ~/.ssh/id_ed25519*你应该看到类似这样的输出-rw------- 1 user user 464 May 15 10:30 /home/user/.ssh/id_ed25519 -rw-r--r-- 1 user user 112 May 15 10:30 /home/user/.ssh/id_ed25519.pub注意私钥的权限必须是600-rw-------否则SSH客户端会拒绝使用它。3. 将公钥添加到Gerrit现在我们需要将公钥添加到你的Gerrit账户。首先复制公钥内容cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard或者如果你没有xclipcat ~/.ssh/id_ed25519.pub然后手动复制输出内容。接下来登录Gerrit网站点击右上角的你的用户名选择Settings在左侧菜单中选择SSH Public Keys点击Add Key按钮粘贴你的公钥内容整个以ssh-ed25519开头的字符串点击Add保存验证密钥是否添加成功ssh -p 29418 your_gerrit_usernamegerrit.example.com如果一切配置正确你应该会看到Gerrit的欢迎消息而不是Permission denied错误。4. 优化SSH配置为了让SSH连接更加可靠和高效我们需要优化~/.ssh/config文件。这个文件允许我们为特定主机定制SSH行为。创建一个或编辑现有的配置文件nano ~/.ssh/config添加以下内容根据你的实际情况修改Host gerrit.example.com HostName gerrit.example.com User your_gerrit_username Port 29418 IdentityFile ~/.ssh/id_ed25519 IdentitiesOnly yes ServerAliveInterval 60 TCPKeepAlive yes配置项解释配置项作用Host定义配置块适用的主机别名HostName实际的主机名或IP地址User登录用户名PortGerrit的SSH端口通常是29418IdentityFile指定使用的私钥文件IdentitiesOnly只使用指定的密钥不尝试其他密钥ServerAliveInterval防止连接超时秒TCPKeepAlive保持TCP连接活跃保存文件后设置正确的权限chmod 600 ~/.ssh/config现在你可以简单地使用以下命令连接Gerritssh gerrit.example.com而不需要记住端口号、用户名等信息。5. 高级技巧与故障排除即使按照上述步骤操作有时还是会遇到问题。这里有一些高级技巧和常见问题的解决方案。多密钥管理如果你需要为不同的Gerrit服务器使用不同的密钥可以这样配置Host gerrit.company1.com IdentityFile ~/.ssh/id_ed25519_company1 Host gerrit.company2.com IdentityFile ~/.ssh/id_ed25519_company2调试SSH连接当遇到问题时添加-vvv参数获取详细日志ssh -vvv gerrit.example.com常见错误及解决方案Bad file permissions确保~/.ssh目录权限为700确保私钥文件权限为600确保config文件权限为600Agent admitted failure to sign运行ssh-add ~/.ssh/id_ed25519将密钥添加到ssh-agent确保ssh-agent正在运行eval $(ssh-agent -s)连接超时检查ServerAliveInterval设置检查网络连接和防火墙设置性能优化对于慢速网络连接可以启用压缩Host gerrit.example.com Compression yes6. 维护与最佳实践配置好SSH密钥后还需要定期维护以确保安全性。密钥轮换每6-12个月生成新密钥对将新公钥添加到Gerrit后再删除旧密钥在~/.ssh/config中更新IdentityFile路径如果需要备份策略备份你的~/.ssh目录特别是config文件和私钥私钥备份必须加密存储考虑使用密码管理器存储重要密钥信息多设备同步如果你在多台设备上工作可以为每台设备生成单独的密钥对将所有公钥添加到Gerrit使用相同的~/.ssh/config配置安全注意事项永远不要将私钥通过电子邮件发送或上传到云存储使用强密码保护私钥在公用电脑上避免永久存储私钥考虑使用硬件安全模块(HSM)或智能卡存储高敏感度密钥7. 自动化与集成将SSH配置与你的开发工作流集成可以进一步提高效率。Git配置确保Git使用正确的SSH密钥访问Gerritgit config --global core.sshCommand ssh -F ~/.ssh/config脚本示例创建一个测试连接的脚本test-gerrit-connection.sh#!/bin/bash SERVERgerrit.example.com USERyour_username PORT29418 echo Testing SSH connection to Gerrit... ssh -p $PORT ${USER}${SERVER} 21 | grep -q Welcome to Gerrit Code Review echo Success! || echo Failed!CI/CD集成在自动化流程中使用SSH密钥时为CI系统创建专用密钥对限制该密钥的权限将私钥存储在CI系统的安全变量中在构建脚本中配置SSHmkdir -p ~/.ssh chmod 700 ~/.ssh echo $SSH_PRIVATE_KEY ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 cat EOF ~/.ssh/config Host gerrit.example.com HostName gerrit.example.com User git IdentityFile ~/.ssh/id_ed25519 StrictHostKeyChecking no EOF8. 替代方案与未来展望虽然Ed25519是目前推荐的选择但了解其他选项也很重要。其他密钥类型比较类型安全性性能兼容性推荐程度Ed25519高优现代系统★★★★★ECDSA高优较好★★★★☆RSA-4096高良最好★★★☆☆RSA-2048中良最好★★☆☆☆DSA低差过时不推荐未来趋势量子安全算法如NTRU、McEliece可能会成为下一代标准FIDO/U2F硬件密钥支持正在被添加到OpenSSH中短期来看Ed25519仍是最平衡的选择向后兼容性如果你必须使用RSA密钥例如某些旧系统可以在~/.ssh/config中临时启用Host legacy-server PubkeyAcceptedKeyTypes ssh-rsa但请尽快迁移到更安全的替代方案。