精通 SSH 代理和代理转发,实现无缝身份验证
安全使用ssh-agent和代理转发,处理带密码的密钥、跳板主机和多跳SSH工作流。
掌握SSH代理与代理转发,实现无缝认证
安全外壳(SSH)密钥认证比可重复使用的密码更安全,但当你连接多个主机时,密码短语可能会拖慢你的速度。ssh-agent通过在当前登录会话中保持解锁的密钥可用解决了这个问题,而代理转发则允许你通过受信任的跳板主机使用这些本地密钥。谨慎使用,这能让你在不将私钥复制到服务器的情况下获得更流畅的SSH访问。
理解SSH代理
ssh-agent是一个后台程序,它安全地将你的私有SSH密钥以解密状态保存在内存中,随时可用。你无需每次连接远程服务器时都输入密码短语,只需在将密钥添加到代理时输入一次。这显著提高了工作流效率,同时不牺牲密码短语保护所提供的安全性。
启动和管理SSH代理
启动代理并使其套接字可用于你的shell会话的过程至关重要。在大多数现代Linux和macOS系统上,代理通常由系统的初始化脚本或桌面环境自动启动。
如果需要手动启动,请使用以下命令序列。这确保了必要的环境变量(SSH_AUTH_SOCK和SSH_AGENT_PID)为当前shell会话正确设置:
# 启动代理并输出必要的环境变量
eval "$(ssh-agent -s)"
向代理添加密钥
代理运行后,使用ssh-add命令将私钥加载到其内存中。如果密钥受密码短语保护,系统会提示你输入。
示例:添加默认密钥
ssh-add
# 按提示输入密码短语
# 身份已添加:/home/user/.ssh/id_ed25519 (user@localbox)
示例:添加特定密钥文件
ssh-add ~/.ssh/my_project_key
验证已加载的密钥
你可以使用-l标志检查代理当前管理的密钥:
ssh-add -l
# 输出示例:
2048 SHA256:abcdef1234567890... user@localbox (RSA)
在私钥上使用密码短语。代理仅节省你在会话期间重复输入密码的麻烦;它不会使磁盘上未受保护的私钥更安全。
解密SSH代理转发
代理转发是一个强大的功能,它允许你使用本地ssh-agent中加载的密钥来认证从第一个远程主机连接的第二个远程主机。
这对于多跳工作流非常有用,例如从笔记本电脑连接到堡垒主机,然后从该堡垒主机连接到内部服务器。
代理转发的工作原理
当你启用代理转发连接到主机A时,SSH会在主机A上创建一个特殊的UNIX域套接字。该套接字充当代理。当你尝试从主机A SSH到目标主机B时,主机A的SSH客户端通过此代理套接字将认证请求转发回本地机器上运行的ssh-agent。代理使用存储的私钥处理加密挑战,并将成功信号发送回去,从而完成对主机B的认证。
你的私钥不会离开本地机器。远程主机获得的是临时代理套接字的访问权限,而不是密钥文件本身。
启用代理转发
要在连接远程主机时启用代理转发,请在ssh命令中使用-A标志:
ssh -A user@bastion-host
你也可以在~/.ssh/config中为受信任的主机进行配置:
Host bastion-host
Hostname 192.168.1.100
User myuser
ForwardAgent yes
测试代理转发
成功连接到启用了转发的堡垒主机后,测试代理套接字是否在远程机器上可用。你可以检查SSH_AUTH_SOCK环境变量是否存在,或在远程机器上使用ssh-add -l:
在堡垒主机上:
# 检查密钥是否已转发(本地运行的代理应响应)
ssh-add -l
# 如果成功,你将看到本地代理管理的密钥。
现在,你可以从堡垒主机使用密钥认证SSH到内部目标主机,而无需在堡垒主机上存在私钥文件:
在堡垒主机上:
ssh user@target-host
# 通过转发的代理套接字,使用本地密钥无缝完成认证。
安全考虑
代理转发很方便,但它会改变你的风险状况。
当在远程主机上启用转发时,具有该主机root访问权限的用户通常可以在你的SSH会话打开期间访问你转发的代理套接字。他们无法从代理读取你的私钥,但可能能够要求代理为你可访问的其他服务器签署认证挑战。
缓解策略
- 默认关闭转发: 仅在需要特定多跳任务时使用
-A。 - 在
~/.ssh/config中限制转发: 仅为受信任的跳板服务器启用转发。Host trusted-jump ForwardAgent yes Host untrusted-server ForwardAgent no - 要求敏感密钥确认:
ssh-add -c ~/.ssh/keyname会在代理使用该密钥前要求确认。当转发的代理暴露给你管理但并非完全信任的主机时,这很有帮助。 - 不需要转发时优先使用
ProxyJump: 如果你的目标只是通过堡垒主机访问私有主机,ssh -J user@bastion user@target通常可以避免将代理转发到堡垒主机。
管理代理生命周期
管理代理的生命周期是一个好习惯,尤其是在手动操作时。当你关闭终端会话时,代理可能仍在后台运行,消耗资源并可能使套接字保持活动状态。
移除密钥
要从代理内存中移除特定密钥:
ssh-add -d ~/.ssh/my_project_key
要从代理中移除所有密钥:
ssh-add -D
停止代理
要终止代理进程并清除内存中所有加载的密钥:
ssh-agent -k
这会输出shell命令以取消设置相关的环境变量并杀死代理进程。如果你使用eval "$(ssh-agent -s)"启动了代理,请运行eval "$(ssh-agent -k)"以将清理应用于当前shell。
关键要点
日常密钥处理使用ssh-agent,并将代理转发保留给确实需要的受信任跳板主机。对于简单的堡垒主机访问,先尝试ProxyJump;对于转发的代理,保持会话简短,并使用ssh-add -d或ssh-add -D移除不再需要的密钥。