SSH Agent Forwarding 在 tmux 中失效的问题记录
问题:在本地通过 SSH 登录远程服务器并进入后者的 tmux session 时,经常遇到 GitHub SSH 认证失败问题:
1 | [email protected]: Permission denied (publickey). |
SSH Agent Forwarding 在 tmux 中失效的问题记录
问题现象
在本地通过 SSH 登录远程服务器时,已经开启了 SSH agent forwarding,例如本地 ~/.ssh/config 中有:
1 | Host <REMOTE_HOST_ALIAS> |
登录服务器后,在普通 shell 中测试 GitHub SSH 认证正常:
1 | echo $SSH_AUTH_SOCK |
可以看到类似输出:
1 | /tmp/ssh-XXXX/agent.<PID> |
但进入之前长期运行的 tmux session 后,再执行:
1 | ssh -T [email protected] |
却报错:
1 | [email protected]: Permission denied (publickey). |
或者在 Git 仓库里执行:
1 | git pull |
报错:
1 | [email protected]: Permission denied (publickey). |
原因
这是 SSH agent forwarding 和长期存活的 tmux session 共同使用时的常见问题。
本地 SSH agent 转发到服务器后,会在服务器上生成一个临时 socket,例如:
1 | /tmp/ssh-XXXX/agent.<PID> |
当前 shell 通过环境变量 SSH_AUTH_SOCK 找到这个 socket:
1 | echo $SSH_AUTH_SOCK |
但是 tmux session 启动后会保存当时的环境变量。之后即使重新 SSH 登录服务器,新的 shell 得到了新的 SSH_AUTH_SOCK,旧 tmux session 也不会自动更新。
因此,旧 tmux 里可能仍然指向过期的 socket,导致 GitHub SSH 认证失败。
这个问题通常出现在以下组合中:
1 | SSH agent forwarding |
这不是 GitHub key 损坏,也不是 remote 配置错误;本质上是 tmux 中的 SSH_AUTH_SOCK 过期。
短期解决方案
重新 SSH 登录服务器后,在普通 shell 中确认当前有效的 socket:
1 | echo $SSH_AUTH_SOCK |
假设输出为:
1 | /tmp/ssh-XXXX/agent.<PID> |
进入 tmux 后手动更新:
1 | export SSH_AUTH_SOCK=/tmp/ssh-XXXX/agent.<PID> |
然后测试:
1 | ssh-add -l |
如果看到:
1 | Hi <GITHUB_USERNAME>! You've successfully authenticated, but GitHub does not provide shell access. |
说明已经恢复正常。
之后即可执行:
1 | git pull |
也可以在 tmux 外部把当前环境写入 tmux:
1 | tmux set-environment -g SSH_AUTH_SOCK "$SSH_AUTH_SOCK" |
然后在 tmux 内执行:
1 | export SSH_AUTH_SOCK="$(tmux show-environment -g SSH_AUTH_SOCK | cut -d= -f2-)" |
长期解决方案
推荐使用一个固定路径的软链接,让 tmux 永远读取固定的 SSH_AUTH_SOCK 路径。
在每次登录服务器后,把当前有效的 agent socket 链接到固定位置:
1 | ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock |
然后在 tmux 中使用固定路径:
1 | export SSH_AUTH_SOCK="$HOME/.ssh/ssh_auth_sock" |
测试:
1 | ssh-add -l |
如果测试成功,就可以正常使用:
1 | git pull |
为了自动化,可以把下面这段加入服务器上的 ~/.bashrc 或 ~/.zshrc:
1 | # Fix SSH agent forwarding inside long-lived tmux sessions. |
之后流程变为:
1 | ssh <REMOTE_HOST_ALIAS> |
如果认证正常,就可以在 tmux 中直接执行 Git 操作。
注意事项
- 不要在共用服务器上随意放置自己的 GitHub 私钥,尤其不要放到共享目录中。
- 如果已经使用 SSH agent forwarding,通常不需要在服务器上生成或保存 GitHub 私钥。
- 不要在 tmux 中随意执行
eval "$(ssh-agent -s)",这会启动服务器本地的新 agent,可能反而绕开本地转发过来的 agent。 - 如果
ssh -T [email protected]显示认证成功,但git pull仍然失败,需要检查当前 GitHub 账号是否有对应仓库权限,尤其是组织仓库是否需要 SSO 授权。
1 |