通过SSH反向代理连接学校内网服务器

问题的来源

从老师那里借了两台服务器跑数据,但是老师的服务器没有公网ip,只有学校内网ip,故只能在实验室或者图书馆登录。有没有什么办法,能让我在宿舍或者家里,远程连接进这两台学校内网的服务器呢?答案肯定的,那就是 反向代理。前提是,我得有一台有公网ip的服务器(例如,阿里云服务器或VPS都可以)。


什么是代理?

要搞清楚什么是反向代理,就得知道什么是 代理(Proxy)。代理其实就是一个跳板。比如我要去图书馆借一本书,我把要借的书的信息写在纸上,交给图书馆管理员,由图书馆管理员去仓库帮我把书取出来交给我。那我们就说,图书馆管理员是我的代理。

在计算机网络中,代理分为 正向代理反向代理

正向代理

假如我们访问不了某网站,但是代理服务器可以访问,我们可以让代理服务器去帮助我们访问目标网站,并把结果返回给我们。对于远程目标网站来说,它只得到了一次请求记录,并不知道是我们通过代理服务器访问的,因此正向代理隐藏了我们自身的信息,但也取决于代理服务器告不告诉目标网站。对于我们客户端来说,我自己是知道我使用了代理去访问某个网站的。

总的来说,正向代理是一个位于客户端(client)和原始服务器(origin server)之间的服务器(proxy server)。客户端为了从原始服务器取得内容,向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。

正向代理的用途

  1. 访问原来无法访问的资源,如Google
  2. 可以做缓存,加速访问资源,如nginx
  3. 对客户端访问授权,上网进行认证
  4. 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

反向代理

反向代理(Reverse Proxy)就是用来解决文章开头提出的问题的。在一些服务器群中,只有一台服务器(即反向代理服务器)向外接收来自互联网的连接请求。然后将请求转发给其他真正提供服务的服务器。对于远程服务器来说,服务器之间是知道代理的存在的,相反,对于我们客户端来说,我们并不知道我们连接的是一个反向代理服务器,我们只知道我们向对方发起了某请求,并获得了回应。

反向代理的用途

  1. 保证内网的安全:可以使用反向代理提供WAF功能,阻止web攻击。通常,大型网站都会将反向代理作为公网访问地址,Web服务器是内网。
  2. 负载均衡:通过反向代理服务器来优化网站的负载

proxy2
proxy3

正向代理和反向代理的区别

proxy2


使用 SSH 反向代理

回到文章开头的问题,如何使用反向代理,让我无论在哪里都可以访问学校内网的服务器呢?这就需要用到 SSH 的反向代理功能了。在学校内网服务器中,我们可以通过 SSH 设置反向代理,指向一个有公网ip的服务器(作为我们的反向代理服务器),之后用客户端连接公网服务器时,公网服务器会把请求转交给内网服务器,从而间接登录学校的内网服务器,整个过程,我们作为客户端是感知不到代理服务器的存在的。客户端是否能感知代理服务器的存在,是区别正向代理和反向代理的关键。

SSH 参数介绍

1
2
3
4
5
# 反向代理命令
ssh -fCNR

# 正向代理命令
ssh -fCNL

参数说明:

Header One Header Two
-f 后台执行ssh指令
-C 允许压缩数据
-N 不执行远程指令
-R 将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口
-L 将本地机(客户机)的某个端口转发到远端指定机器的指定端口
-p 指定远程主机的端口

学校内网服务器操作

先跑一趟实验室或图书馆,在内网里面进行操作。

1
2
# ssh -fCNR 远程端口:localhost:本地端口 远程用户@远程ip
ssh -fCNR 2999:localhost:22 remote_user@123.123.123.123

这句命令的意思是,将远程公网服务器 2999 端口转发至本地 22 端口, remote_user@123.123.123.123是远程服务器用户名和ip

  • 使用 ps aux | grep ssh 来查看是否运行。

公网服务器操作

恰好我有一台腾讯云服务器学生机,配有公网ip,可以拿这台服务器作为跳板机(远程代理服务器)。

1
2
# ssh -fCNL *:客户端登录端口:localhost:本地端口 localhost
ssh -fCNL *:11111:localhost:2999 localhost

这句命令的意思是,将 11111 端口作为本地转发端口,用于与互联网进行通信,并将数据转发至 2999 端口,而 2999 端口的数据会被刚刚配置的学校内网服务器接收。

登录

现在,用一台位于任意地方的电脑

1
ssh -p11111 学校内网用户名@公网ip地址

这样就可以访问到学校内网了。

免密登录

1
ssh-copy-id 公网用户名@公网ip

用autossh建立稳定隧道

autossh 跟 shh 不同的地方在于,当隧道断开的时候,autossh 会自动重新连接,而ssh不会。

centos 安装(内网服务器操作)

1
yum install autossh

反向代理(内网服务器操作)

1
autossh -M 6666 -fCNR 2999:localhost:22 公网用户名@公网ip

-M参数指定一个端口,这个端口是公网机器用来接收内网机器的信息,如果隧道不正常而返回给内网机器让他实现重新连接。

配置开机启动(内网服务器操作)

1
2
3
vi /etc/rc.d/rc.local
autossh -M 6666 -fCNR 2999:localhost:22 公网用户名@公网ip
chmod +x /etc/rc.d/rc.local

不止SSH

到这里就已经解决了文章一开始的问题了。但是突发奇想,除了ssh之外,有没有办法,能够远程访问没有公网ip的电脑上面架设的Web服务或者Ftp服务呢?例如,在家里的电脑(没有公网ip)上架了一个网站,那出门的时候有没有办法远程访问家里的整个网站?事实上,这是完全可行的,借助的也是反向代理,但有了一个新的名词——内网穿透。现在市面上内网穿透的软件很多,比如花生壳、ngrok,使用这些工具,不仅仅可以反向代理ssh的22端口,还可以代理任意 tcp 或 udp 端口,非常有用。


使用 ngrok 进行内网穿透

ngrok 的官网是 https://ngrok.com/ ,是一个专注于建立反向代理隧道的软件。

ngrok

客户端使用方法

到官网申请一个账号,会得到一个 TOKEN ,下载安装完客户端软件后,执行以下命令即可:

1
2
3
unzip /path/to/ngrok.zip
./ngrok authtoken <YOUR_AUTH_TOKEN>
./ngrok http 8080

这样,你内网机器的80端口即会被映射到公网上了。例如,访问 http://myapp.ngrok.io ,即相当于访问了你内网里面的 127.0.0.1:8080

自己编译服务端软件

ngrok是开源的,可以自己编译服务端软件,并将自己的公网服务器作为反向代理服务器。前提是得有公网ip + 域名(国内需备案)。

由于我没有域名,所以这部分就没有实践了。具体步骤可以参考官方文档教程:https://developer.github.com/webhooks/configuring/


参考资料