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


103

我想访问一台计算机,例如位于我大学网络中的机器A。但是,只能通过大学的内部网络访问此计算机,因此我无法直接从家里对这台计算机使用SSH。

这是我现在要做的:

  1. 登录到另一台大学计算机,例如计算机B

    (可以从我的家用计算机通过SSH访问此机器B。)

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

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


Answers:


97

是的,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 -q0 hostname.or.IP.address.internal.machine 22

现在您可以直接使用

ssh user@internalmachine

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

  • SCP复制文件。

    scp somefile user@internalmachine:~/
    
  • 在您的GUI应用程序中:

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

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

笔记

就像从机器上一样,更改,hostname.or.IP.address.internal.machine然后将端口(22)移至您想到达的unibroker机器。

根据unibroker主机上的netcat版本,-q0必须省略该选项。关于认证;您基本上是在工作站上建立两个SSH连接。这意味着将对unibroker主机和内部计算机主机进行一次又一次的验证/认证(对于密钥对/密码和主机密钥验证)。

说明

这种使用ProxyCommand“ netcat”和“ netcat”的方法只是做到这一点的一种方法。我之所以这样,是因为SSH客户端直接与目标计算机对话,因此我可以从客户端验证主机密钥,并且可以使用公共密钥身份验证,而无需在代理上使用其他密钥。

每个都Host定义新主机部分的开始。Hostname是该主机的目标主机名或IP地址。User是您作为中的用户部分提供的内容ssh user@hostname

ProxyCommand将用作连接到目标计算机的管道。通过在第一台计算机上使用SSH并直接nc从那里建立一个简单的“ netcat”()到目标,这基本上只是从中间代理到内部计算机的纯文本。该-q选项是沉默的任何输出(只是个人喜好)。

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

请注意,此处您仍在两次使用SSH加密。当netcat通道为纯文本时,您PC上的SSH客户端将使用最终目标计算机设置另一个加密通道。


4
我必须删除-q0选项,因为我使用的计算机不支持该选项。除此之外,一切都可行。这是一个奇妙的提示。非常感谢。:)
Gerry

我遇到了一个问题,你的答案工作正常,我从终端,但我无法使用GUI SFTP做到这一点,它说:未处理的错误消息,超时而不能登录。
Vikash乙

@VikashB好吧,它确实应该工作。考虑创建一个新问题来处理您的特定情况。
gertvdijk 2015年

我在这里做这样的问题:askubuntu.com/questions/688567/...
Vikash乙

1
为了补充@gertvdijk的明智之词,有一本关于ssh代理和跳转主机的优秀Wikibook,可以作为无价的参考。
特拉维斯·克拉克

51

一口气跳

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

ssh -t user@machineB ssh user@machineA

注意-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.
[...]

它将强制分配实际的TTY

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

由于上述所有原因,我强烈建议使用ProxyCommand方法,但是对于快速连接而言,它可以很好地工作。


为什么对“一次性”解决方案和永久解决方案都没有一个答案?
demure

5
@demure这就是StackExchange网站的工作方式...请参阅:两次回答问题的正式礼节是什么?说:“发布两个不同的答案比将它们放入一个答案要好。” 。我不认为这是相同的解决方案。我认为,永久性/暂时性并不是使这种方法与众不同的原因。
gertvdijk

其他指南还说,要使用-A开关,但表明这会带来安全隐患。您是否知道转发或不发送身份验证代理连接是什么意思?
对角线

@gertvdijk超级忍者在这里!您有两个最佳解决方案。我从未见过。超酷。比用N个解决方案创建一个百万长的解决方案要好(这是我通常看到的)。
Trevor Boyd Smith

这比设置将同时妨碍其他ssh的配置要方便得多。
Nikhil Sahu

37

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

ssh -J user@machineB user@machineA

来自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.

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


3
+1是因为即使您需要为machineA指定密钥文件,此方法也可以工作
Grief

1
+1,如果您的所有主机最近都在运行OpenSSH版本,则与我的ProxyCommand答案相比,这是更好的版本。
gertvdijk

在这种情况下,应该在A和B机器上都安装OpenSSH服务器吗?我理解正确吗?
米哈伊尔

17

尝试使用

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>

在〜/ .ssh / config中,仅使用计算机上的键就可以一次完成所有操作。


1
这比将netcat引入组合更干净。另外,B机器上也不需要私有SSH密钥。
danemacmillan

1

这是一个非常有用的建议。弄了几个小时后,我找到了这条纸条,并确认其工作原理与所记录的完全相同。要将MachineA通过MachineA连接到远程机器C:

例如:[xuser @ machineC〜] ssh -t MachineA ssh MachineB

“ -t”很关键,如果不存在,ssh将失败。系统将提示您两次,第一次提示您输入MachineA上的密码,然后第二次提示您输入MachineB。另外,请注意,这假设您在所有三台计算机上都定义了用户“ xuser”。如果不是,则仅使用ssh语法:“ yuser @ MachineA ...”。另请注意,如果需要,您可以使用点分四元原始IP#。如果您通过使用未公开给世界各地的IP(即IP)的专用本地网络进行链接,这将非常有用。不在您的本地主机文件或任何DNS中。要从MachineB到远程machineC获取文件,您可以从MachineB到MachineA进行scp,然后从MachineA到远程machineC进行scp。(例如,远程计算机C可以ping通机器A,但不能ping通机器B。)警告:我在Fedora和WindowsXP上进行了测试,MachineA是运行ICS(Internet连接共享)的XP-box,而MachineB和remote machineC是Fedora-Linux机器。这个建议为我解决了一个关键问题-即。受限制的受监控的对我的远程站点局域网的远程访问。另请注意,从MachineB“注销”时,应该看到两个“与xxx.xxx.xxx.xxx的连接已关闭”。消息。


如果您设置并配置了公共密钥身份验证,则无需担心输入密码。但是-t仍然是必需的。
费利佩·阿尔瓦雷斯

@FelipeAlvarez如果您不信任机器B以无密码登录到A,您仍然需要担心输入第二个密码!
迈克尔(Michael)

1

对于在两个系统中都允许外壳程序访问的情况,ProxyCommand是一个干净的解决方案。我们希望给远程用户通过代理(B)访问内部计算机(A)的权限,但不允许用户通过Shell对B的外壳访问来提高安全性。这工作:

更换登录外壳

更换登录shell(使用chsh的)extuser与下面的脚本(存储在一个文件)经纪人:

#!/bin/sh   # this is essential to avoid Exec format error
ssh internaluser@A

如果没有在远程用户的extuser @ B和在extuser @ B的internaluser @ A中设置密码登录,那么执行以下命令将把远程用户直接带到A

ssh extuser@B

提示:在更改为自定义登录外壳之前,请在extuser @ B中创建必要的无密码登录authorized_keys设置。更改之后,由于任何人都无法通过外壳程序访问此帐户,因此只有sudoer @ B可以通过直接对其进行编辑来更改文件authorized_keys。

sudo vi ~extuser/.ssh/authorized_keys
sudo touch ~extuser/.hushlogin

最后一行是禁止显示来自B的登录标语,因此远程用户可以透明地访问A。


非常有趣的方法。但是,这样做的主要缺点是:1)使用仅限于标准SSH使用(不支持SFTP / SCP)。2)用户无法选择除单个主机之外的其他目标主机(因为在登录外壳中进行了硬编码)3)无法从工作站到最终目标主机进行主机密钥验证(因为使用了经纪人SSH二进制文件) 。4)用户访问最终目标主机的私钥驻留在代理上,而不是用户。这允许管理员模仿用户(通常是不可能的)。
gertvdijk

所有观点都是正确的,谢谢您的阐述。但是,主要目的是为受信任的用户提供对A的ssh访问,而无需登录到B。由于只有管理员才能在B上添加受信任用户的公钥(通过sudo,无需登录),这已经意味着该用户具有( admin)访问extuser @ B的私钥(不是外部受信任用户的私钥),并首先进行了设置!
桑塔尔'16

1

您的意思是您需要几个跳线:)

最近,我遇到了跳线1跳线2和我的最终机器的问题,至于我的溶胶

本地脚本:

#!/bin/bash
sshpass -p jumper1Passwd ssh -t jumper1@jumper1IP ./Y00.sh

然后在第一个跳线(这是我的路由器)上,放置了一个名为Y00.sh的脚本:

ssh -tt jumper2@jumper2 -i ~/.ssh/id_rsa sshpass -p finalPassWord ssh -tt final@final

您可以用您的IP和密码替换这些,祝您好运!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.