如何在一个命令中通过 B SSH 到机器 A?

nik*_*sdi 141 ssh networking remote-access tunnel

我想访问一台计算机,比如位于我大学网络中的机器 A。但是,这台电脑只能通过大学内部网络访问,所以我不能直接从家里使用SSH连接到这台电脑。

这是我现在要做的:

  1. 登录到不同的大学机器,比如机器 B

    (这台机器 B 可以从我的家用电脑通过 SSH 访问。)

  2. 在 B 上使用 SSH 连接到 A。

有没有办法更快地做到这一点?仅使用一个 ssh 命令。

ger*_*ijk 126

使用ProxyCommand您的SSH配置。

在您的主目录中创建一个 SSH 配置文件(除非您想在系统范围内创建此文件)~/.ssh/config,:

Host unibroker          # Machine B definition (the broker)
Hostname 12.34.45.56    # Change this IP address to the address of the broker
User myusername         # Change this default user accordingly 
                        # (`user@unibroker` can overwrite it)

Host internalmachine    # Machine A definition (the target host)
ProxyCommand ssh -q unibroker nc hostname.or.IP.address.internal.machine 22
Run Code Online (Sandbox Code Playgroud)

现在您可以直接使用

ssh user@internalmachine
Run Code Online (Sandbox Code Playgroud)

另请注意,现在您有一个 SSH 主机目标名称,您也可以在其他应用程序中使用它。例如:

  • SCP复制文件。

    scp somefile user@internalmachine:~/
    
    Run Code Online (Sandbox Code Playgroud)
  • 在您的 GUI 应用程序中:

    使用sftp://user@internalmachine/作为位置来浏览计算机上。

    基于 KDE (Dolphin):使用 fish://user@internalmachine/

笔记

hostname.or.IP.address.internal.machine将端口 ( 22)更改为您想要访问的机器,就像从unibroker机器上一样。

根据 unibroker 主机上的 netcat 版本,-q0必须省略该选项。关于认证;您基本上是从您的工作站设置两个 SSH 连接。这意味着 unibroker 主机和内部机器主机都被一个接一个地验证/认证(用于密钥对/密码和主机密钥验证)。

解释

这种使用ProxyCommand和“netcat”的方法只是一种方法。我喜欢这个,因为我的 SSH 客户端直接与目标机器对话,这样我就可以从我的客户端验证主机密钥,并且我可以使用我的公钥身份验证而无需在代理上使用另一个密钥。

每个Host定义一个新主机部分的开始。Hostname是该主机的目标主机名或 IP 地址。User是您作为ssh user@hostname.

ProxyCommand将用作到目标机器的管道。通过在第一台机器上使用 SSH 并nc从那里直接设置一个简单的“netcat”()到目标,这基本上只是从它们之间的代理转发到内部机器的明文。该-q选项是沉默的任何输出(只是个人喜好)。

确保您在代理上安装了 netcat(通常在 Ubuntu 上默认可用) - netcat-openbsd安装 netcat-openbsdnetcat-传统安装 netcat-traditional.

请注意,您仍然在这里使用了两次加密的 SSH。虽然 netcat 通道是纯文本的,但您 PC 上的 SSH 客户端将与最终目标机器建立另一个加密通道。

  • 我不得不删除 -q0 选项,因为我使用的机器不支持它。除此之外,一切都奏效了。这是一个很棒的提示。非常感谢。:) (4认同)
  • 为了补充@gertvdijk 的明智之词,有一本关于 [ssh 代理和跳转主机](https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Proxies_and_Jump_Hosts) 主题的很棒的 wikibook,可以作为无价之宝参考。 (2认同)

Eri*_*und 69

您可以使用-J命令行选项:

ssh -J user@machineB user@machineA
Run Code Online (Sandbox Code Playgroud)

来自man ssh

-J [user@]host[:port]
     Connect to the target host by first making a ssh connection to
     the jump host and then establishing a TCP forwarding to the
     ultimate destination from there.  Multiple jump hops may be
     specified separated by comma characters.  This is a shortcut to
     specify a ProxyJump configuration directive.
Run Code Online (Sandbox Code Playgroud)

它是在OpenSSH 7.3 版(2016 年 8 月发布)中引入的。它在 Ubuntu 16.10 及更高版本中可用。

  • +1 因为即使您需要为 machineA 指定密钥文件,这也有效 (4认同)
  • +1,如果您的所有主机都运行足够新的 OpenSSH 版本,那么与我的 ProxyCommand 答案相比,这是更好的版本。 (2认同)

ger*_*ijk 62

一口气跳下去

我在其他答案中提供的 ProxyCommand 方法的一个明显替代方法是直接“跳转”到目标机器:

ssh -t user@machineB ssh user@machineA
Run Code Online (Sandbox Code Playgroud)

注意-t第一个ssh命令。没有它,它将失败:

Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
Permission denied, please try again.
[...]
Run Code Online (Sandbox Code Playgroud)

它将强制分配一个真正的 TTY

这样做的缺点是现在所有配置、验证和身份验证都在机器 B 上进行,出于安​​全原因,我真的不喜欢这种情况。我喜欢在我自己的 PC 上使用我的密钥对,并从我自己的 PC 上验证和验证最终目标机器。此外,您只能将交互式 shell 用于 SSH,因此这不会处理其他工具,例如 SCP 或使用您的 GUI 文件管理器。

由于上述所有原因,我强烈推荐ProxyCommand 方法,但对于快速连接,这很好用。

  • @demure 这就是 StackExchange 网站的工作方式...请参阅:[回答问题两次的官方礼节是什么?](http://meta.stackexchange.com/q/25209) 说 *“最好发布两个不同的答案,而不是把它们放在一个答案中。”*。我不认为这是相同的解决方案。在我看来,永久/临时并不是使这种方法不同的原因。 (7认同)

小智 19

尝试使用

Host <visible hostname alias>
        Controlmaster auto
        User <user>
        hostname <visible hostname>
        port <port>
        IdentityFile ~/.ssh/<id file>

Host <private LAN hostname alias>
     ProxyCommand ssh -q -W <private LAN hostname>:<private LAN port> <visible hostname alias>
Run Code Online (Sandbox Code Playgroud)

在您的 ~/.ssh/config 中,并使用仅驻留在您计算机上的密钥一次性完成所有操作。

  • 这比将 netcat 引入混合更干净。此外,“B”机器上也不需要存在私有 SSH 密钥。 (2认同)

小智 8

machineA是最终目标。\nmachineB是经纪人。

\n

我们希望通过 ssh 轻松完成home -- machineB -- machineA

\n

OpenSSH 7.3 版本(2016 年 8 月发布)或更高版本中,您可以执行以下操作之一:

\n

.ssh/config方法:

\n

将以下行添加到您的.ssh/config

\n
Host machineB\n    Hostname 12.12.12.12           # IP of machineB (w.r.t. home)\n    User usernameB                 # username on machineB\n\nHost machineA\n    Hostname 34.34.34.34           # IP of machineA (w.r.t. machineB)\n    ProxyJump usernameB@machineB   # PROXY MAGIC!\n    User usernameA                 # username on machineA    \n
Run Code Online (Sandbox Code Playgroud)\n

然后输入ssh machineA. 也与 兼容。\n您可以通过https://unix.stackexchange.com/a/494485scp增强上述配置以强制使用特定的密钥。

\n

-J标志选项:

\n

只需输入ssh -J usernameB@machineB usernameA@machineA.

\n

最后的笔记

\n

此答案结合了 gertvdijk 和 Erik Sj\xc3\xb6lund 的答案以及https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Proxies_and_Jump_Hosts#cite_note-ProxyJump-1上的指南。

\n