ssh -A(SSH Agent Forwarding):这是最常用、最核心的“SSH 代理”功能,它允许你将本地的 SSH 私钥安全地“传递”到远程服务器上,用于继续跳转到其他服务器。ProxyCommand:这是一个更底层的配置,允许你指定一个命令(通常是另一个 SSH 连接)来建立与最终目标主机的连接,常用于创建复杂的网络路径。
我会重点讲解第一种,因为它解决了绝大多数代理场景的需求,然后简要介绍第二种。

核心概念:SSH Agent Forwarding (ssh -A)
它是什么?
想象一下这个场景:
- 你的电脑(本地机器, Laptop)在 A 网络。
- 有一台跳板机(堡垒机, Bastion Host),它在 B 网络,你只能通过 SSH 密钥登录它。
- 在跳板机后面,有一台数据库服务器(目标服务器, Target Server),它只能在堡垒机所在的网络中访问,并且也只接受来自堡垒机的 SSH 密钥登录。
没有 Agent Forwarding 时的麻烦做法:
- 你需要将你的私钥(
id_rsa)复制一份到堡垒机上。 - 设置好权限
chmod 600 ~/.ssh/id_rsa_on_bastion。 - 每次从堡垒机登录到目标服务器时,都需要输入密码(如果私钥有密码)或者手动指定密钥文件。
这种做法很糟糕,因为它:
- 不安全:你的私钥副本会留在堡垒机上,增加了泄露风险。
- 不方便:需要手动同步密钥,如果私钥更新了,还得再复制一遍。
- 不灵活:如果你有多个开发者,每个都需要在堡垒机上配置自己的密钥。
使用 SSH Agent Forwarding (ssh -A) 的优雅做法:
你只需要一条命令:

# -A 参数开启了 Agent Forwarding ssh -A user@bastion-host
登录到堡垒机后,你发现可以直接无密码登录到目标服务器:
# 在 bastion-host 上执行 ssh user@target-server
神奇之处在于: ssh -A 告诉堡垒机:“嘿,当我需要验证身份时,不要用你本地的私钥,而是帮我向我的本机(Laptop)的 SSH Agent 请求一个临时的、一次性的签名。” 整个过程是加密和安全的,你的私钥从未离开过你的本地机器。
它是如何工作的?
-
本地启动 SSH Agent:你的本地机器上必须有一个正在运行的
ssh-agent,它会缓存你的私钥,并响应签名请求。- 检查是否运行:
echo $SSH_AUTH_SOCK(如果输出一个路径,说明正在运行)。 - 启动它:
eval "$(ssh-agent -s)"。 - 添加私钥到 Agent:
ssh-add ~/.ssh/id_rsa(它会提示你输入密码,之后一段时间内就无需再输)。
- 检查是否运行:
-
建立连接:当你执行
ssh -A user@bastion时:
(图片来源网络,侵删)- 你的本地
ssh客户端连接到堡垒机。 - 它在连接中包含了一个特殊的“认证代理协议”信息,告诉堡垒机:“我有一个可用的认证代理,地址是 ”。
- 你的本地
-
远程服务器上的行为:当你从堡垒机再执行
ssh user@target时:- 目标服务器会向堡垒机请求你的公钥进行验证。
- 堡垒机不会用自己的私钥,而是它会反向连接回你的本地机器的
ssh-agent(通过之前建立的加密通道)。 - 本地
ssh-agent收到请求,用你的私钥对一段随机数据进行签名,然后将签名发回给堡垒机。 - 堡垒机将这个签名转发给目标服务器。
- 目标服务器用你的公钥验证这个签名,如果成功,就允许你登录。
如何使用?
命令行方式(临时生效):
# 登录到远程服务器,并开启 Agent Forwarding ssh -A user@remote-host # 如果已经登录了,可以重新打开一个会话来开启 ssh -A user@remote-host
配置文件方式(永久生效,推荐):
编辑你的 ~/.ssh/config 文件,为需要代理的主机添加 ForwardAgent yes。
# ~/.ssh/config
# 为堡垒机配置 Agent Forwarding
Host bastion
HostName 192.168.1.100
User myuser
ForwardAgent yes
# 为目标服务器配置,并指定通过堡垒机跳转
Host target
HostName 10.0.0.50
User myuser
# 这一步是可选的,但能简化命令
ProxyCommand ssh -W %h:%p bastion
# ProxyCommand 没用,也可以手动登录 bastion 后再登录 target
# ForwardAgent yes # 如果堡垒机是中间跳板,这个配置通常加在 bastion 的 Host 条目里就够了
# 另一个例子:所有 github.com 的连接都通过代理
Host github.com
HostName github.com
User git
# 假设你的代理服务器地址是 proxy.example.com
ProxyCommand nc -X 5 -x proxy.example.com:1080 %h %p
配置好后,你就可以直接登录了:
ssh target # 会自动通过 bastion 跳转,Agent Forwarding 也生效了
进阶概念:ProxyCommand
ProxyCommand 是一个更底层的工具,它不关心认证,只关心如何建立网络连接,它告诉 ssh 客户端:“不要直接连接目标主机,而是先执行我给你的这个命令,然后将该命令的标准输入和输出作为与目标主机通信的通道”。
它是什么?
ProxyCommand 允许你将 ssh 的输入和输出“管道”给另一个命令,这个命令通常是另一个 ssh 进程,用于建立跳板,但它也可以是 nc (netcat) 或其他任何可以建立网络连接的程序。
如何使用?
最经典的用法是通过一个中间服务器跳转。
示例:通过跳板机连接目标服务器
假设你有:
- 跳板机:
bastion.example.com - 目标服务器:
db.internal.com(无法从外网直接访问)
使用 ssh -W (现代、简洁)
这是目前推荐的方式,ssh -W 会自动处理数据转发。
在你的 ~/.ssh/config 中:
Host bastion
HostName bastion.example.com
User myuser
Host db
HostName db.internal.com
User myuser
# 告诉 ssh: 先通过 bastion 建立一个隧道,然后将所有通信转发到 db 的 22 端口
ProxyCommand ssh -W %h:%p bastion
你只需要执行 ssh db,ssh 会自动在后台执行 ssh -W db.internal.com:22 bastion,为你建立好连接。
使用 nc (Netcat)
如果跳板机上没有 nc 或者你想用更通用的方式,可以这样配置:
Host db
HostName db.internal.com
User myuser
# 在 bastion 上执行 nc,连接到 db 的 22 端口
# %h 会被替换成 db.internal.com, %p 会被替换成 22
ProxyCommand ssh bastion nc %h %p
这种方式要求你的跳板机上安装了 nc 并且能正常工作。
命令行方式(临时生效):
# 手动输入密码,比较繁琐 ssh -o "ProxyCommand ssh user@bastion nc %h %p" user@db.internal.com # 结合 Agent Forwarding,更强大 ssh -A -o "ProxyCommand ssh -A user@bastion nc %h %p" user@db.internal.com
总结与对比
| 特性 | ssh -A (Agent Forwarding) |
ProxyCommand |
|---|---|---|
| 目的 | 身份验证代理:将本地私钥安全地用于远程服务器。 | 连接代理:通过一个中间主机建立到目标主机的网络通道。 |
| 解决的问题 | 避免将私钥复制到跳板机上,简化多级服务器的登录流程。 | 解决网络隔离问题,通过一个可访问的中间主机连接到内网或防火墙后的主机。 |
| 工作层面 | 在认证层面工作。 | 在网络连接层面工作。 |
| 典型用法 | ssh -A user@bastion Host ... ForwardAgent yes |
Host ... ProxyCommand ssh -W %h:%p bastion Host ... ProxyCommand ssh bastion nc %h %p |
| 依赖 | 需要本地 ssh-agent 正在运行并加载了私钥。 |
不依赖 ssh-agent,但需要中间主机能执行连接命令(如 nc 或另一个 ssh)。 |
最佳实践:
-
首先配置
~/.ssh/config,把所有主机、用户、端口、代理规则都写好,这是最方便、最不容易出错的方式。 -
对于需要跳板机的场景,将
ForwardAgent yes和ProxyCommand结合使用,可以实现一次登录,畅通无阻。# ~/.ssh/config Host bastion HostName 1.2.3.4 User ec2-user ForwardAgent yes Host app-server HostName 10.0.1.55 User app-user ProxyCommand ssh -W %h:%p bastion你只需要在本地运行
ssh app-server,就能无密码、无感地通过堡垒机登录到应用服务器,并且所有后续的scp、git等操作都能自动使用你的本地私钥。
