如何让 SSH 的 `ControlPath` 区分 IPv4 和 IPv6?

n.s*_*.st 5 ssh openssh

我正在使用

ControlMaster   auto
ControlPath     ~/.ssh/tmp/%l_%r@%h:%p
Run Code Online (Sandbox Code Playgroud)

在我~/.ssh/config通过 SSH 访问主机时使用相同的连接打开多个会话。

这适用于大多数用例,但不允许我同时通过 IPv4 和 IPv6 连接到相同的主机名;所有附加连接都使用第一个连接创建的控制套接字,因为ControlPath它不允许区分 IPv4 和 IPv6 连接。

有没有办法为 IPv4 和 IPv6 连接提供单独的控制套接字(也许通过找到一种使用远程 IP 而不是套接字路径中的远程主机名的方法)?


编辑#1

我只记得和文件中Match可用的选项并尝试过:ssh_configsshd_config

Match AddressFamily inet
    ControlPath     ~/.ssh/tmp/%l_%r@%h:%p.inet

Match AddressFamily inet6
    ControlPath     ~/.ssh/tmp/%l_%r@%h:%p.inet6
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我尝试连接到任何主机时,“不支持的匹配属性 AddressFamily ”失败了,所以我又回到了原点……

n.s*_*.st 0

我已将我的答案分成两个单独的答案,以便您可以分别对“包装器”和“补丁”方法进行上/下投票。

解决方案1:编写包装函数

ssh ()
{
    controlpath=""
    for argument in $@
    do
        if [[ "$argument" = "-"*"4"* ]]
        then
            controlpath="~/.ssh/tmp/%l_%r@%h:%p.inet"
        fi
        if [[ "$argument" = "-"*"6"* ]]
        then
            controlpath="~/.ssh/tmp/%l_%r@%h:%p.inet6"
        fi
    done

    if [ -n "$controlpath" ]
    then
        /usr/bin/ssh -o "ControlPath=$controlpath" $@
    else
        /usr/bin/ssh $@
    fi
}
Run Code Online (Sandbox Code Playgroud)

该包装函数将指示sshssh hostssh -4 host和创建单独的控制套接字ssh -6 host
它可能无法正确解析类似的内容ssh -464466 host(即使技术上允许),但它应该是简单场景的最简单的解决方法。