我搭建同实验室已有几年。(也许以后会再详细介绍一下!)我经常需要 ssh 连接到其中一台服务器。

在家时,我可以直接使用类似下面的域名:

ssh ahoy.m.example.ca
ssh bread.m.example.ca

我在家使用 Split-Horizon DNS 并借助 DNSMasq 实现了该配置,因此这些域名仅在家时解析。

外出时,我会使用一台“堡垒”服务器,通过 ssh 连接它后再跳转到其他服务器。该服务器使用一个“秘密”端口。

为了让 SSH 自动通过堡垒服务器,我在 ~/.ssh/config 中添加了以下配置:

Host *.m.example.ca
    ForwardAgent yes
    User evert
    ProxyCommand ssh -q -W %h:%p -l evert bastion.example.ca -p 6767

bastion.example.ca 会解析到真实的 IP(我家的公网 IP)。这样做的烦恼在于,无论我在家还是外出,只要使用上述命令,都会先走堡垒服务器。

最近我了解到 MatchProxyJump 指令,并拼凑出了下面这段配置:

Match host *.m.example.ca exec "! getent hosts %h >/dev/null"
    ForwardAgent yes
    User evert
    ProxyJump [email protected]:6767

它与之前的配置效果相同,只是这条规则仅在 getent hosts %h 命令执行失败时才会生效。

ProxyJumpProxyCommand 更简洁。我想这个指令已经存在一段时间了,但我过去十几年一直只是复制粘贴 ProxyCommand

你可能没有类似的 DNS 设置,而是使用 .local 域名访问本地服务器,这种情况下下面这段配置也适用,但需要注意:

Match host *.local exec "! getent hosts %h >/dev/null"
    HostName %h
    ForwardAgent yes
    User evert
    ProxyJump bastion.example.ca:6767

每次执行时,你的计算机通常会先在本地网络广播寻找目标主机。.local / MDNS 在本地访问时速度也会稍慢。考虑到你已经承担了这部分开销,ForwardAgent 还会带来额外的风险:有人可能冒充 target.local 并获取你整个 SSH 密钥链的访问权限。因此,对于这种情况,也许始终通过堡垒服务器反而更安全。如果你需要这样的配置,可以使用:

Host *.local
    HostName %h
    ForwardAgent yes
    User evert
    ProxyJump bastion.example.ca:6767

这样对所有 .local 主机的 SSH 连接都始终走堡垒服务器。