当客户端和主机在同一台机器上时,ssh如何工作?

我用docker container的帮助来说明我的问题,但是这个例子与问题的其他部分是正交的。 事实上,任何允许使用接接口和ssh的程序都可以。

我使用一个Docker容器,它在前台运行的supervisord产生的背景中运行一个sshd守护进程。 我主要使用ssh有一个X11转发的安全方式,而不必绑定/tmp/.X11-unix到可以容器和完全暴露到容器的sockets。 如果我在启动容器后立即使用docker top containername ,那么将得到以下输出:

 UID PID PPID C STIME TTY TIME CMD root 4732 535 1 19:56 ? 00:00:00 /usr/bin/python /usr/bin/supervisord root 4745 4732 0 19:56 ? 00:00:00 /usr/sbin/sshd 

这是预期的。 现在,我把容器上的端口22暴露在主机上的端口5000上。 因此,我可以使用ssh -X username@localhost -p 5000login到我的容器中。 我知道客户端和主机是不同的计算机和不同的networking时,ssh是如何工作的,但当客户端和主机是同一台计算机(在我的情况下,客户端是我的普通机器,主机是我的普通机器上的容器)时,我有一些问题。 我知道docker在我的普通机器上的物理networking设备和我的机器上的虚拟networking设备之间架起了一座桥梁。

  1. 但是我的普通机器和容器之间究竟是如何相互通信的呢? 他们是否使用由桥接设备分配给他们的IP地址并通过它们进行通信?

  2. 在这个过程中涉及到的端口如何消除了使用IP地址的需要?

  3. 当客户端和主机位于同一台计算机上并按照我刚才所述的方式进行configuration时,是否存在使用ssh的最有效/最推荐的方法?

广泛的互联网search没有揭示足够的答案。 话虽如此,我当然不会断言这样的网站不存在!

当地通讯如何运作? 这很简单:就像普通的非本地通信一样,除了networking堆栈检测到通信的目的地在同一台机器上,所以它不需要将stream量顺着堆栈交给物理层,而是通过它到IP层的接收部分。

特别是,这意味着IP地址仍然是必要的,因为IPnetworking连接总是需要源端口和地址以及目的地端口和地址 – “特殊”部分就是源地址和目的地址相同,在这种情况下是127.0.0.1/localhost

从SSH或任何其他networking协议的angular度来看,什么都不会改变。

就虚拟化而言,有两种方法:桥接networking和NAT。

  • 借助桥接networking,虚拟机是networking的完整成员,拥有自己的地址和一切。 这工作如下:
    • 虚拟化软件在主机中创build虚拟networking接口,以反映虚拟机内的模拟物理设备。
    • 在主机上,创build一个网桥并将虚拟设备和物理设备绑定到它。 这就像一个交换机,物理设备作为networking其余部分的上行链路。
    • 就像一个真正的交换机一样,网桥设备知道连接到哪个IP地址,并相应地传输stream量,并且不会在连接到网桥的(虚拟)设备之一的线路上发送stream量。 在networking堆栈中,它位于链路层。
  • 使用NAT,就像大多数家庭networking一样,您不能直接与虚拟机通信,而必须将主机用作路由器。
    • 您仍然有虚拟接口连接到(虚拟)交换机。 但是这个交换机并不像网桥那样工作,也没有连接到物理networking。
    • 主机的networking接口连接到物理networking和虚拟networking,充当NAT路由器。 如果要直接与虚拟机通话,则必须进行端口转发。

我不确定Docker究竟是如何运作的,可能是使用另一种方法,只是将物理主机上的端口直接连接到虚拟机的端口,而不需要整个NAT。

在你的SSH例子中,在后台实际上发生了很多事情:

  • 如果您执行ssh user@localhost -p 5000 ,则networking堆栈会检测到这是本地的,并且不会在线路上发送stream量。 而是将其发送到本地机器的5000端口。
  • 正在端口5000上侦听的NAT转发器将stream量发送到虚拟接口,并将虚拟接口作为正常stream量从虚拟机接收到端口22。