跳转至

利用HTTPS隧道取代传统隧道

注意

请勿使用本文技术去做违法的事情,比如翻看国家禁止的资源,应当科学上网!

背景

我们都知道,利用传统隧道技术(如:“L2TP/IPSec”)可以实现安全访问,尤其当我们有一些资源无法访问时。由于当前主流的客户端都支持L2TP/IPSec,比如手机、平板和电脑;因此使用该技术不仅可以轻松实现安全访问,而且没有额外的技术成本。

但有时就是那么的不巧,由于一些原因导致在某些时段内无法使用传统隧道技术,具体原因这里就不详细陈述了,嘿嘿。因此是否有什么方法可以在这种状况下,可以临时取代传统隧道实现安全访问呢?尤其是当我们着急想要查阅资料时,此时若无法进行安全访问会非常耽误事。

我们知道,除了“L2TP/IPSec”之外,当前主流客户端都支持“Web代理(HTTP隧道)”来访问Web资源。但问题是其访问时非安全的。那么是否有什么办法来实现“安全Web代理(HTTPS)”呢?


方案介绍

假设我们此时有以下几个角色:

  1. 搜索服务(W1):提供搜索服务,部署于内网受到“S”的管控,域名为“search.server.com”。
  2. 视频服务(W2):提供视频服务,部署于内网受到“S”的管控,域名为“multimedia.server.com”。
  3. 服务器(S):部署于公网,可以访问“W1”和“W2”,域名为“s.server.com”。
  4. 笔记本电脑(C):教学电脑,给学生在校外使用。
  5. 流代理(P):提供代理功能,能进行SSL卸载和加密,域名为“p.server.com”。

我们有此情景:“C”需要通过“S”,来访问“W1”搜索资料或访问“W2”观看教学视频。

在此之前都是在笔记本电脑上用“L2TP/IPSec”来与“S”建立安全连接,之后间接的通过“S”来访问“W1”和“W2”:

L2TP/IPSec

由于上述方案在一些特殊状况下无法使用,因此我们考虑到使用“HTTP隧道”: HTTP隧道

  • 如上所示,使用WEB代理的话,“C”与“S”建立的是TCP连接(红虚线),因此在两者之间是用明文传递代理请求的。显然如此的话便无法实现安全访问,因此在“C”和“S”之间是可以被窃取和干预的,比如:一个中间人“M”,为了让“C”挂科,于是监听其通信过程,一旦发现是访问“W1”或“W2”的域名就拦截请求,或则伪造RESET给“S”报文,强行关闭连接。

为了避免明文“HTTP隧道”带来的风险,因此我们需要使用“HTTPS隧道”,为了不进行额外开发,我们决定在“C”本地部署“流代理(P)”来完成此需求:

  • 如上所示,“P”在左侧提供TCP监听,监听来自“C”的流量,并在代理给“S”请求之前,与“S”建立SSL安全连接。最终“C”与“S”实现了安全通信,于是在“C&P”和“S”之间的“M”再也没法干预了。 HTTP隧道

实施

服务器(S)

要在服务器提供WEB代理服务,只需要使用“Hengine”或“Tengine”项目即可,这里使用基于“Tengine”二次开发的“Hengienw”的容器homqyy/hengine:1.0,nginx配置文件如下:

worker_processes 2;

user root;

error_log logs/info.log info;
error_log logs/debug.log debug;

events {
    use epoll;
    worker_connections 1024;
}

http {
    #
    # 基础配置
    #
    sendfile on;

    proxy_http_version 1.1;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;  

    #
    # 作为安全WEB代理服务器
    #
    server {
        listen 10443 ssl;         # 监听 10443端口,且开启SSL协议
        server_name s.server.com; # S服务器的域名

        # SSL证书和密钥
        ssl_certificate certs/s.server.com/fullchain.pem;
        ssl_certificate_key certs/s.server.com/privkey.pem;

        # 启用WEB代理,即代理CONNECT请求
        proxy_connect;
        proxy_connect_allow             443;
        proxy_connect_connect_timeout   60s;
        proxy_connect_read_timeout      60s;
        proxy_connect_send_timeout      60s;

        proxy_set_header Host           $host;

        # 转发所有非CONNECT的请求
        location / {
            proxy_pass https://$host;
        }
    }
}

本地环境(C&P)

“P”使用Nginx即可,当然也可以直接使用“Hengine”。将其运行在笔记本电脑上,这里使用的是原生的Nginx容器nginx:latest,其Nginx配置文件如下:

worker_processes 1;

user root;

error_log /var/log/nginx/info.log info;

events {
    use epoll;
    worker_connections 1024;
}

stream {

    server {
        listen 10080;    # 监听10080端口,笔记本电脑需要把流量代理到这

        proxy_ssl on; # 代理数据前,先与服务器建立SSL安全连接

        # 代理到S服务器,假设服务器的WEB代理端口为:10443
        proxy_pass s.server.com:10443;
    }
}

笔记本电脑(C)则只需要设置网页代理即可,即将请求代理到“P”上,这里以MacOS为例:

笔记本设置网页代理

访问服务

这时候我们假设部署的“W1”服务为“百度”或其它搜索引擎(you understand),在笔记本上访问结果如下:

笔记本访问W1

评论