在 SSH 中每个主机使用两个不同的 IP 地址

在 SSH 中每个主机使用两个不同的 IP 地址

我有一台名为 的服务器gamma,在工作中不断启动并运行。有时我从家里连接到它,在这种情况下我使用公共 IP 地址55.22.33.99。有时,我在工作时连接到它,而不是不必要地反弹我的数据包,我通过本地 IP 地址进行连接192.168.1.100

目前,我将它们分成两个不同的条目~/.ssh/conf

Host gamma-local
        HostName 192.168.1.100
        Port 22
        User andreas

Host gamma-remote
        HostName 55.22.33.99
        Port 12345
        User andreas

所以,如果我在工作,我只需输入即可ssh gamma-local;如果我在家(或世界其他地方),我会跑步ssh gamma-remote

连接到服务器时,我宁愿不必根据我所在的位置输入不同的名称,我宁愿该部分自动完成;例如,在某些情况下,我有自动脚本可以连接那些不知道我在哪里的人。

使用 Bash 脚本解决此问题的问题首先“尝试”连接到本地,如果无法连接,则尝试连接到远程 IP 地址。这很好,但是(1)似乎效率低下(特别是因为有时您必须“等待”连接超时,因为它们并不总是立即发回错误)并且(2)需要 Bash 并拖拽脚本。

是否有另一种方法可以实现此目的,既不依赖于 Bash 脚本的使用,也不首先“测试”连接是否有效?

答案1

如果您有办法识别您所在的网络,那么您可以使用Match关键字~/.ssh/config做你想做的事。这需要 OpenSSH ≥6.5。

我用类似的东西

Match originalhost gamma exec "[ x$(/sbin/iwgetid --scheme) != xMyHomeESSID ]"
  HostName 192.168.1.100
  Port 22

Host gamma
  User andreas
  Port 12345
  HostName 55.22.33.99

因此,我使用所用 wifi 网络的标识符来确定我是否在家用于 SSH 连接,但也可以使用检查分配给您计算机的 IP 地址或任何其他可以区分这两个网络的内容。

答案2

如果您碰巧在工作中拥有私人名称服务器,并且您在办公室和家里使用同一台笔记本电脑,则可以利用它来实现此目的:

  1. 修改你的nsswitch.conf机器以首先检查 DNS
  2. gamma在办公室的私有 DNS 中创建一个 DNS 条目以解析为 192.168.1.100。
  3. 在计算机的 /etc/hosts 文件中创建一个条目以解析gamma为 55.22.33.99。

这样,当您ssh gamma在办公室时,它将从办公室 DNS 解析为 192.168.1.100,当您从家里连接时,它将从您的主机文件解析为 55.22.33.99。

聚苯乙烯:此答案假设您不希望 gamma 有公共 DNS 条目。另外,如果您从 Windows 计算机通过 SSH 连接到服务器,我认为应该有一些相当于 nssswitch.conf 文件的地方来覆盖主机文件条目。

答案3

几年前,我写过一个程序出于类似的目的。它可能适合您的需求。使用该程序,ssh 配置可能如下所示:

Host gamma
    ProxyCommand ssh-multipath-proxy 192.168.1.100:22 55.22.33.99:12345
    User andreas

答案4

~/.ssh/config使用 IP 地址作为主机名时无法实现此目的。事实上,您不仅连接到不同的 IP 地址,还连接到不同的端口,这一事实带来了额外的复杂性,因为这几乎排除了对 DNS 解析器的任何调整。

我纠正了 - 你可以使用Match originalhost ... exec ...组合~/.ssh/config- 请参阅@MichałPolitowski 的回答。然而,尽管它对于 OpenSSH 来说可以完美工作,但您可能不一定在其他 SSH 客户端中找到类似的功能。

您可以使用一个简单的包装器(如果您需要从各种 shell 中使用它,则可以是 shell 函数或脚本)来解决该问题ssh,它将检查您所在的网络并使用适当的Host条目。最大的问题是,如何可靠地检测您所在的网络。我会想到本地 IP 地址,但它并不可靠,因为您可能从使用与工作网络相同子网的 LAN 进行连接。

如果您可以为本地和远程网络使用相同的端口,您可以/etc/resolv.conf根据您所在的网络进行编辑 - 显然它必须自动完成(很可能是通过 DHCP 客户端的挂钩脚本)。或者 - 更好 - 运行本地名称服务器(例如dnsmasq)并为其提供适当的配置。但这超出了这个问题的范围。

另一种选择 - 如果您只需要交互连接 - 是使用可扫描的命令完成~/.ssh/config。这将节省您的打字时间(特别是如果您有足够多的不同Host条目)。像这样的东西(用于bash初始化):

# complete session names for ssh
declare -g _ssh_complete_hostlist 2> /dev/null
function _ssh_complete_init () {
    _ssh_complete_hostlist=$( \
        sed -nr '/^\s*Host\s*=/{s/^[^=]+= *//;s/ /\n/g;p}' ~/.ssh/config \
        | sort )
}
_ssh_complete_init

function _ssh_complete () {
    local match=${COMP_WORDS[${COMP_CWORD}]}
    local hosts=
    local default=
    for h in $_ssh_complete_hostlist; do
        if [[ $h =~ ^$match ]]; then
            hosts="$hosts $h"
        fi
    done
    if ! (( ${COMP_CWORD} == ${#COMP_WORDS[@]}-1 )); then
        default=$( compgen -f ${COMP_WORDS[${COMP_CWORD}]} )
    fi
    COMPREPLY=($hosts $default)
}
complete -F _ssh_complete ssh

第一个函数创建一个完成主机的列表(通常在每个 shell 中运行一次就足够了),第二个函数执行实际的完成,尽管方式有点笨拙 - 它只在主机名是时才完成主机名。命令行上的最后一个标记。

综上所述,解决此问题的正确方法是通过 VPN 连接到工作网络,从而可以像在办公室一样访问本地工作 IP 地址。然后,您可以将地址硬连接到您喜欢的任何一层:~/.ssh/config/etc/resolv.conf(恕我直言,最好的选择)办公室名称服务器。

相关内容