对ssh反向连接、端口转发命令的理解

最近思考内网穿透的问题,联想到ssh的反向连接,于是学习了一下相关的命令。网上ssh命令详解的文章很多也很专业,这里我想用通俗的方式再说一下自己对ssh命令的理解。

1 问题描述

我在A学校,小伙伴在B学校。小伙伴在配置Linux环境的时候遇到些问题,来请求我的帮助。我想直接登录他的系统查错,可学校A和学校B属于两个不同的内网,互相不通,这可咋办呢?

对ssh反向连接、端口转发命令的理解_第1张图片
问题描述

2 解决方法

2.1 思路

使用ssh反向连接。这里先简单描述一下ssh反向连接的效果,先有一个感性的认识,下文会进一步探究其原理。

ssh反向连接,顾名思义,反过来连接。
通俗点解释,就是我先ssh主动连接你,建立起一条通道,使你能通过这条通道反向连接回我

那什么时候会用到ssh反向连接呢?
最常见的应用场景就是我在内网中,而你在公网中。你想连接我,正常情况下是做不到的。但是通过ssh反向连接,就可以满足这个需求。

对ssh反向连接、端口转发命令的理解_第2张图片
反向连接

但是现在的情况是我和我的小伙伴都在内网中啊,要怎么使得两个内网中的电脑互相连通呢?
让我们来曲线救国。我们需要借助一台公网电脑来做牵线红娘,这里我使用的是自己的vps。下面给出具体方案。

2.2 方案

对ssh反向连接、端口转发命令的理解_第3张图片
曲线救国

分两步走

  1. 小伙伴使用ssh远程端口转发命令,和公网电脑建立通道,使公网电脑有途径反向连接回小伙伴电脑。
  2. 我再ssh连接公网电脑,然后操作公网电脑ssh连接小伙伴电脑。

2.3 具体命令

  1. 小伙伴需要执行的操作
    a. 使用ssh远程端口转发命令,和公网电脑建立通道。
ssh -R 6666:localhost:22 <公网电脑>

-R 参数即表示远程端口转发。
这条命令的意思是,小伙伴与公网电脑约定,发往公网电脑6666端口的数据会原封不动地转发到小伙伴电脑的22端口上。
所以之后,在我连接到公网电脑后,只需要操作公网电脑,利用公网电脑的6666端口,即可连接回小伙伴的电脑。
这便是我上文说的那条能够反向连接回小伙伴的通道。

对ssh反向连接、端口转发命令的理解_第4张图片
小伙伴的操作

上面的马赛克是我vps的ip地址,即公网电脑的ip地址,大家替换成自己的就好。

一般在使用的时候,还会加上 -f -C -N 这3个参数。
-f 表示后台运行。不加这个参数的话,小伙伴的终端就被ssh命令占用,不能接收其他命令输入了。
-C 表示压缩数据。
-N 表示不执行远程命令。不加这个参数的话,小伙伴将连接公网电脑,登录公网电脑的终端。

注意
选择公网电脑端口的时候,注意不要选择已经使用的端口,不然之后反向连接的链路会建立失败。

对ssh反向连接、端口转发命令的理解_第5张图片
注意
  1. 我需要执行的操作
    a. 先ssh连接公网电脑
    常用命令,就不作过多解释了。执行完这条命令,将连接公网电脑,登录公网电脑的终端。
ssh连接公网电脑

b. 然后操作公网电脑ssh连接小伙伴电脑

ssh -p 6666 baba@localhost

-p 参数表示指定端口。
这条命令的意思是使用ssh,访问localhost的6666端口,来连接baba这个用户。
结合上文远程端口转发的操作,发往公网电脑6666端口的数据会原封不动地转发给小伙伴电脑的22端口,也就是说在公网电脑上ssh访问localhost的6666端口,实际上是访问了小伙伴电脑的22端口,故这条命令的效果是远程登录小伙伴的电脑。

对ssh反向连接、端口转发命令的理解_第6张图片
公网电脑ssh连接小伙伴电脑

如上图所示,登录baba用户之后,查看ip地址,是内网地址,说明确实登录了内网中小伙伴的电脑。

至此,就解决了两台内网主机通信的问题。

3 命令理解

ssh反向连接命令本质上使用的是ssh的端口转发功能。
具体来说,反向连接使用的是远程端口转发功能(-R参数),这里我想和本地端口转发功能(-L参数)对比来理解。

先给出两种用法的命令格式:

远程端口转发:ssh -R ::
本地端口转发:ssh -L ::

还记得第一次接触这两条命令的时候,把我整蒙了。使用的时候,local和remote,到底哪个是哪个;有时候local指自己,remote指别人,有时候又反过来,把我搞得晕头转向;还有这个SSH host与local和remote又是什么关系。太难了。

我查阅了不少资料,排列组合这些参数做了一些实验,思考了很久才把这几个参数理清楚。这里我想用通俗一些的方式,解释这几个参数,希望能给刚接触ssh端口转发命令的同学们一点帮助。

3.1 铺垫

首先强调一个小细节:

不要将 ssh反向连接ssh远程端口转发 混为一谈。

ssh连接都是由自己发起,去连接别人,建立一条通道。这里 -L/R 参数约定的是这条通道的端口转发的方向。
当使用 -R 参数时, 这条通道是反向转发数据,别人的ssh连接请求可以借助这条通道转发回自己,实现反向连接的目的。
注意这里存在两个ssh连接,一个是ssh远程端口转发建立的连接,另一个是ssh反向连接建立的连接,不要混为一谈了。

注意到这个细节,对于理解命令是有很大帮助的。

在解释命令之前,让我们再约定几个词语:ssh端口转发的起点我们叫做local,终点我们叫做remote。
也就是说,local和remote的定义 与 是否是ssh端口转发命令的发起者,没有必然联系,而是根据端口转发的方向来定义的。

弄清楚local与remote的定义,命令理解起来就不那么难了。
我们来改写一下端口转发命令:

端口转发:ssh -L/R <起点 port>:<终点 host>:<终点 port>

我更喜欢写成这种格式,逻辑更加清楚:

端口转发:ssh -L/R <起点 port>:<终点 host>:<终点 port>

这样命令的意思就比较清晰了:先通过ssh连接别人,再和别人约定好端口转发的起点和终点信息,建立起端口转发的通道。

铺垫完毕,下面举例辅助理解。

3.2 举例

  1. 远程端口转发
    将公网电脑的6666端口的数据转发给自己的22端口。这里数据转发方向是由 公网电脑的端口 到 自己的端口,故命令为
ssh -R <公网电脑 port>:<自己 ip>:<自己 port> <公网电脑> 

ssh -R 6666:localhost:22 <公网电脑>
  1. 本地端口转发
    将自己6666端口的数据转发给公网电脑的22端口。这里数据转发方向是由 自己的端口 到 公网电脑的端口,故命令为
ssh -L <自己 port>:<公网电脑 ip>:<公网电脑 port> <公网电脑>

ssh -L 6666:<公网电脑 ip>:22 <公网电脑>

当然也可以写成

ssh -L 6666:localhost:22 <公网电脑>

这种写法可能很多人都有疑惑:这个localhost是什么鬼?不是公网电脑的ip吗,怎么还能写成localhost?

这条命令曾经也让我困惑了很久,所以我特地把它拎出来,和大家聊一聊我的理解。

大家可以先做一个简单的实验,上面<终点 ip>信息,可以写成 <公网电脑 ip>,可以写成 localhost ,可以写成 127.0.0.1 ,但是不能写成自己电脑的ip,否则进行端口数据转发的时候会失败。
这个现象说明,这里填 localhost 或 127.0.0.1 其实并不是指代自己电脑,而是指代公网电脑。也就是说,这个 localhost 是从公网电脑的角度来看的。

阶段性总结

我们再重新理一下ssh命令:

ssh -L/R <起点 port>:<终点 ip>:<终点 port> 

我们先通过ssh连接别人,再和别人约定好端口转发的起点和终点信息。

怎么约定呢?对于本地端口转发(-L参数),转发方向由自己到别人,起点信息是从自己电脑的角度来看,终点信息是从的角度来看。当<终点 ip>为 localhost 的时候,是告诉把它自己作为端口转发的终点。
而对于远程端口转发(-R参数),转发方向由别人到自己,起点信息是从别人()的角度来看,终点信息是从自己电脑的角度来看


  1. 进阶例子
    现在有A,B,C三台电脑。假设A和C不通,但A能和B互通,C也能和B互通。在这种情况下,A怎么和C建立通信呢?
对ssh反向连接、端口转发命令的理解_第7张图片
进阶例子

让我们学以致用,使用端口转发命令,借助A-B这个通道,使A与C建立通信。
首先在A这台电脑上,执行这条命令:

ssh -L : :    

有了上面的基础,这条命令应该不难理解了。A在终端执行这条命令,先通过ssh连接上B,然后和B约定转发的起点和终点信息,建立起端口转发的通道。

然后在A这台电脑上,再执行这条命令,使用刚刚建立的端口转发通道,就能连接上C电脑:

ssh -p  C@localhsot

这里A直接使用本地端口转发就能连上C,是因为B和C能互通,所以不需要麻烦C去和B建立反向连接。如果B和C之间是单向通信,只能C连B的话,就需要使用 2.2 方案,先麻烦C通过远程端口转发去建立和B的反向连接,来帮助A连上C。

所以需要注意这点,这里的终点必须是B能访问的电脑,否则数据转发会失败。

  1. 最后一个例子
    现在有A,B,C,D四台电脑。假设A和D不通,但A能和B互通,D能和C互通,B和C能通信。在这种情况下,A怎么和D建立通信呢?
最后一个例子

让我们举一反三,使用端口转发命令,借助B-C这个通道,使A与D建立通信。
首先在B这台电脑上,执行这条命令:

ssh -g -L : :    

这里使用了一个新的参数,-g 参数。如果不使用这个参数,这个端口的数据来源只能是B电脑,其他电脑往B电脑这个端口发的数据不会被接收。加上 -g 参数后,其他电脑就也能使用这个端口进行数据转发了。

然后在A这台电脑上,只需要执行这条命令,使用刚刚建立的端口转发通道,就能连接上D电脑:

ssh -p  D@

4 实际应用

实际上,ssh端口转发命令除了能用于ssh连接,还能做很多事情。下面模拟一个应用场景:借助ssh端口转发,来远程连接mysql服务器。通过这个应用场景,完整地走一遍流程。

4.1 问题描述

类似 3.2 举例中的最后一个例子,现在有A,B,C,D四台电脑。A是我的电脑,D是我想连接的mysql服务器。假设A和D不通,但A能和B互通,D能和C互通,B和C能通信。在这种情况下,我(A)要怎么连接上mysql服务器(D)呢?

对ssh反向连接、端口转发命令的理解_第9张图片
实际应用

四台电脑的ip地址如上图所示。

4.2 流程步骤

至始至终,我只需要坐在A电脑前进行操作。

  1. 首先ssh连接B电脑。
ssh [email protected]
  1. 连上B电脑后,在B电脑上配置本地端口转发。
ssh -gfCNL 6666:192.168.12.104:3306 [email protected]

解释:将B电脑6666端口的数据 经由C电脑 转发到D电脑的3306端口上。

  1. 断开与B的ssh连接,在A的终端上输入命令,远程连接mysql服务器。
mysql  -h 192.168.12.102  -P 6666   -uroot  -p

解释:通过B电脑的6666端口连接mysql服务器。

至此,我便成功连接上了mysql服务器。

4.3 实际意义

可能有人会质疑,整得这么花里胡哨的,真的用得上吗。整这么麻烦,什么时候还需要通过端口转发去连接一个服务呢?
比如这种情况:

对ssh反向连接、端口转发命令的理解_第10张图片
实际意义

内网1是一个诈骗团伙窝点,D是存放各种信息的数据库,C(可以有多台)是骗子们的电脑。为了安全,C和D是主机模式,D只能和C互通,不能和外界通信。而B是这些骗子们访问外界资源的出口。

我(A),是正义的化身,要把诈骗团伙数据库中的数据拖出来,作为证据提供给警察叔叔,为人民除恶。

那么就可以用到这种技术。

醒醒……
端口转发技术当然有很多非常有价值的应用场景。不过本文的目的是和大家分享一下对ssh反向连接、端口转发命令的理解,就不对应用场景做过多描述了。

5 总结

再回顾一下ssh端口转发命令的格式:

ssh -L/R <起点 port>:<终点 ip>:<终点 port> 

先通过ssh连接,再和约定好端口转发的起点和终点信息,建立起端口转发的通道。

最后用一个比喻作为本篇文章的总结:

  1. 通过ssh端口转发命令,建立起一条数据管道:
  1. 管道中数据可以想象成水流,当使用本地端口转发时(-L参数),管道中的水从cilent端流向server端;当使用远程端口转发时(-R参数),管道中的水从server端流向cilent端。
对ssh反向连接、端口转发命令的理解_第11张图片
  1. 管道的起点有一张过滤网,终点有一个发射器。建立管道时,起点信息,是对水流入口说的,用来过滤数据;终点信息,是对水流出口说的,用于精准投放数据。
对ssh反向连接、端口转发命令的理解_第12张图片
  1. 当<终点 ip>为localhost时,表示将数据投放给水流出口自己。对于本地端口转发(-L参数),就是指SSH server;对于远程端口转发(-R参数),就是指SSH client。

你可能感兴趣的:(对ssh反向连接、端口转发命令的理解)