SSH代理转发场景下:如何保留本地~/.ssh目录内的ed25519-sk密钥并仅向低版本OpenSSH服务器转发兼容密钥?
这个问题我之前也碰到过,低版本OpenSSH(比如RHEL7的7.2版本)对ed25519-sk这类硬件密钥的兼容性确实有坑——当代理转发时,只要有一个不兼容的密钥存在,整个密钥列表都会被服务器端的代理拒绝,导致连能用的密钥也传不过去。下面给你几个实用的解决方案,既能把ed25519-sk密钥留在本地~/.ssh目录,又能只转发兼容的密钥:
方法一:通过SSH配置文件指定仅加载兼容密钥(推荐)
这是最省心的持久化方案,通过~/.ssh/config针对目标RHEL7服务器做单独配置,强制SSH只加载你指定的兼容密钥,不会碰ed25519-sk的密钥:
Host rhel7-* # 匹配所有RHEL7服务器的主机名,可改成具体IP或域名 HostName %h User your-username ForwardAgent yes IdentitiesOnly yes # 强制只使用下面指定的密钥,不自动加载所有密钥 IdentityFile ~/.ssh/id_rsa # 替换成你的兼容密钥路径 IdentityFile ~/.ssh/id_ecdsa # 有多个兼容密钥就多加几行
配置好之后,你连接这些服务器时,SSH只会把上面指定的兼容密钥加载到代理并转发,ed25519-sk密钥会留在本地,不会被发送到服务器端,自然就不会触发格式错误了。
方法二:临时手动管理代理中的密钥
如果你只是偶尔连接这些RHEL7服务器,可以临时清空代理里的所有密钥,再只添加兼容的:
- 先清空当前代理的所有密钥:
ssh-add -D
- 添加你需要转发的兼容密钥:
ssh-add ~/.ssh/id_rsa ~/.ssh/id_ecdsa
- 这时候再连接RHEL7服务器,代理里就只有兼容密钥,转发就能正常工作了。
之后需要用ed25519-sk密钥时,再执行ssh-add ~/.ssh/id_ed25519_sk把它加回代理即可。这个方法适合临时场景,不用改配置,但每次都要手动操作。
方法三:使用独立的代理套接字分开管理密钥
如果需要同时维护两个代理环境(一个带ed25519-sk,一个只带兼容密钥),可以用独立的代理套接字:
- 创建并启动一个专门用于RHEL7连接的代理:
export SSH_AUTH_SOCK=/tmp/ssh-compat-agent ssh-agent -a $SSH_AUTH_SOCK ssh-add ~/.ssh/id_rsa ~/.ssh/id_ecdsa
- 连接RHEL7服务器时,指定使用这个代理:
ssh -o IdentityAgent=/tmp/ssh-compat-agent your-rhel7-server
或者直接把代理路径加到~/.ssh/config里,省得每次输:
Host rhel7-servers HostName your-server-ip User your-username ForwardAgent yes IdentityAgent /tmp/ssh-compat-agent
这样平时正常使用时,默认代理还是包含ed25519-sk密钥的,只有连接RHEL7服务器时才用专门的兼容代理,两者互不干扰。
补充说明
为什么原本的转发会失败?因为低版本OpenSSH的ssh-agent在解析密钥列表时,遇到ed25519-sk这种它不认识的格式,会直接抛出「invalid format」错误,并且终止整个密钥列表的读取,导致连兼容的密钥也无法被识别。上面的方法本质都是让本地代理只向服务器端发送兼容的密钥,避免低版本代理碰到不认识的格式。
备注:内容来源于stack exchange,提问作者Powerriegel

