原因

下午上密码学,看到讲解ssh端口转发的内容,书中讲的实在太模糊了,于是上网找相关内容自学


本文实现目标

1、ssh本地端口转发讲解

2、ssh远程端口转发讲解与windows上演示

正文

1、ssh本地端口转发

image-20220530162552209

适合的状况

  • 本地主机hostLocal(图中左边)无法访问私网主机hostPrivate(图中右边)
  • 本地主机可以访问云服务器
  • 私网主机可以访问云服务器
  • 云服务器可以访问私网主机非常重要啊,能和下面的远程端口转发区分开)
  • 云服务器无法访问本地主机

为了实现的目标

  • 本地主机可以访问私网主机

思路

  • 因为本地主机可以连接到云服务器,那可以借助云服务器,近一步访问到私网主机

整体流程

  1. 本地主机设置一个端口(假如为)2233(目的是,以后本地主机可以通过端口2233访问私网主机
  2. 给目标私网主机设置一个端口(假如为)7788(目的是:可以在此端口运行web服务网页,当然也可以设置为FTP协议对应的21端口)。当然,私网主机也有一个私网ip嘛,假如为52.77.56.16
    • 先明确一点:云服务器是可以访问到这个私网ip:52.77.56.16,以及对应的7788端口
  3. 云服务器也有公网ip(假如为)39.45.55.12。而且开放了默认的、用来给ssh连接的端口22,当然这个端口也可以修改成其它的号码
  4. 本地主机运行ssh命令
  5. 本地主机访问2233端口,会访问到私网主机的web服务。完成

注意

  • 虽然,我这里叫私网主机为“私网”,但这个私网,可以是任何的、相对于本地主机来说“不能访问的网络”。如:国内用户要翻墙就是这个原理
  • 所以,我上面的私网Ip,并没有写一个“局域网ip”,而是一个公网主机Ip,但这个公网主机可能无法直接连接

原理

  1. 本地主机通过ssh协议连接上云服务器的公网ip:端口22,让本地主机云服务器创建了一条隧道,并且本地主机的ssh将监听2233端口收到的所有请求
  2. 本地主机如果对2233端口进行访问,ssh将这个请求会通过隧道转发云服务器
  3. 云服务器再将这个请求转发私网主机的7788端口
  4. 私网主机接收请求,将回应发送到云服务器
  5. 云服务器再将回应,通过隧道转发到本地主机

至此,所有的理论就解释完成。

ssh命令实操

这条命令在本地主机执行

1
ssh -L [本地主机ip:]2233:52.77.56.16:7788 root@39.45.55.12

这个看着十分混乱,对应的解释为

本地ip 本地端口 私网主机ip 私网主机端口 云服务器ip
可选的 2233 52.77.56.16 7788 root@39.45.55.12
自定义端口 必须是云服务器能访问的ip 自定义端口 root是用户名
  • 这个私网主机相对云服务器而言的,如果这个私网主机是云服务器里面运行的docker程序,那私网ip应该是localhost。再比如,下面使用本地转发翻墙时,也会用localhost。

结果

  • 本地主机访问2233端口时,相当于访问了私网主机的7788端口服务

2、ssh远程端口转发

image-20220530175834997

适合的状况

  • 任意主机(图中左侧)无法访问私网主机(图中右边)
  • 任意主机可以访问云服务器
  • 私网主机可以访问云服务器
  • 云服务器无法访问私网主机这一条与上面的本地端口转发不同
  • 云服务器无法访问任意主机

为了实现的目标

  • 任意主机可以访问私网主机

思路

  • 因为云服务器无法访问私网主机,无法做本地端口转发,但私网主机可以连接云服务器,于是,还是可以让云服务器成为跳板

整体流程

  1. 私网主机设置一个端口开放为4000(后面会在此端口开放web程序或其它传输服务)
  2. 云服务器的公网ip如39.45.55.12,并设置一个端口为6789。那39.45.55.12:6789是一个公网ip+端口,可以让任意主机访问
  3. 私网主机运行ssh命令(后面会配置)
  4. 私网主机4000端口开放一个web服务,如运行了一个网页
  5. 任意主机打开浏览器,输入39.45.55.12:6789,会访问在私网主机运行的web服务。完成

原理

  1. 私网主机通过ssh协议连接上云服务器的公网ip:端口22,让任意主机云服务器创建了一条隧道,并且私网主机的ssh将监听4000端口收到的所有请求,注意:私网主机在端口4000开放了一个web服务
  2. 任意主机访问云服务器39.45.55.12:6789时,云服务器会将任意主机请求通过上面建立的隧道转发私网主机的4000端口
  3. 私网主机再将响应回复给云服务器
  4. 云服务器再将响应转发任意主机

ssh命令

因为这条命令是在私网主机上运行,所以,localhost是指私网主机的本地网络服务

1
$ ssh -R [远程ip]:6789:localhost:4000 root@39.45.55.12

对应的解释为

云服务器端口允许访问的ip 云服务器端口 私网主机ip 私网主机端口 云服务器ip
0.0.0.0 6789 localhost 4000 root@39.45.55.12
让所有ip都可以访问 自定义端口 不用修改 自定义端口 root是用户名

注意

  • 如果云服务器是linux,需要在私网主机上设置[远程Ip]0.0.0.0,因为默认情况下,linux不允许各种外网的ip都能访问本地的网络服务。

  • 另外,需要在云服务器上修改sshd_config,将里面的GateWayPortyes,如下图

1
2
3
4
5
$ vim /etc/ssh/sshd_config
# 修改GateWayPort 为yes
# 注意去除前面的 # 号
# 保存
$ systemctl restart sshd
  • image-20220530183424208

结果

  • 任意主机访问公网ip+端口39.45.55.12:6789时,相当于访问了私网的4000端口服务
    • 如下图所示,我在私网主机打开了hexo的web服务,理伦上来说,只能私网主机自己能访问。但经过上面的远程端口转发后,任意主机访问公网后,也能访问私网的web服务
    • image-20220530183534047

两种转发的用处

本地端口转发

  • 最直接的,做正向代理,翻墙
  • 如果把上面“本地端口转发”的教程中,“私网”修改成“国外网”,私网主机Ip修改成国外网的ip,那……不是就相当于,国内的主机,通过云服务器访问国外网吗???(当然这个云服务器要可以访问国外网)

ssh翻墙举例

如果我们的翻墙服务器的地址是123.222.111.54,用户名是ss,翻墙服务器开放的端口是1111,使用下面的命令:

1
ssh -L 2233:localhost:1111 ss@123.222.111.54

我们就可以将我们本地的2233端口映射到翻墙服务器的端口1111上,服务器上无需安装其它服务即可实现翻墙。

当然,还需要将自己浏览器的代理,设置成使用本地2233端口。

我推荐用SwitchyOmega这个浏览器插件,安装好这个插件后,配置如下图即可,端口要自行修改。

image-20220614201848314

注意

但这种方式并不真正的安全,很早前就被GFW能检测到,只有万不得已的情况下使用

远程端口转发

  • 可以在本地电脑部署一些web应用,在本地电脑执行上面的ssh命令(注意开放好服务器的对应端口和本地电脑的端口)

随后,任意电脑或手机就可以直接访问云服务器间接地访问本地电脑的web服务,这应该是内网穿透吧。

并且,用了远程端口转发后,服务器其实根本没有运行什么web服务,只是个网络转发工具


云服务器充当的角色

本地端口转发

  • 在本地端口转发中,云服务器应该是正向代理服务器,因为需要本地手动设置代理的服务器地址真正想要访问的地址

远程端口转发

  • 在远程端口转发中,云服务器是反向代理服务器,因为真正访问云服务器的手机或电脑,不知道自己访问的是代理服务器,以为访问的就是真正的web服务器(或其它服务)。而且,这些手机或电脑无需做任何设置。

还有个透明代理的概念啊,这里并没有用上……


下面是转载自阮一峰

SSH其它的参数

N参数

表示只连接远程主机,不打开远程shell;T参数,表示不为这个连接分配TTY。这个两个参数可以放在一起用,代表这个SSH连接只用来传数据,不执行远程操作。

1
$ ssh -NT -D 8080 host

f参数

表示SSH连接成功后,转入后台运行。这样一来,你就可以在不中断SSH连接的情况下,在本地shell中执行其他操作。

1
$ ssh -f -D 8080 host

要关闭这个后台连接,就只有用kill命令去杀掉进程。


参考

b站up主DavyCloud的讲解:https://www.bilibili.com/video/BV1C7411P7Er?p=1

阮一峰ssh解读:https://www.ruanyifeng.com/blog/2011/12/ssh_port_forwarding.html