利用HTTPS隧道取代传统隧道
注意
请勿使用本文技术去做违法的事情,比如翻看国家禁止的资源,应当科学上网!
背景¶
我们都知道,利用传统隧道技术(如:“L2TP/IPSec”)可以实现安全访问,尤其当我们有一些资源无法访问时。由于当前主流的客户端都支持L2TP/IPSec,比如手机、平板和电脑;因此使用该技术不仅可以轻松实现安全访问,而且没有额外的技术成本。
但有时就是那么的不巧,由于一些原因导致在某些时段内无法使用传统隧道技术,具体原因这里就不详细陈述了,嘿嘿。因此是否有什么方法可以在这种状况下,可以临时取代传统隧道实现安全访问呢?尤其是当我们着急想要查阅资料时,此时若无法进行安全访问会非常耽误事。
我们知道,除了“L2TP/IPSec”之外,当前主流客户端都支持“Web代理(HTTP隧道)”来访问Web资源。但问题是其访问时非安全的。那么是否有什么办法来实现“安全Web代理(HTTPS)”呢?
方案介绍¶
假设我们此时有以下几个角色:
- 搜索服务(W1):提供搜索服务,部署于内网受到“S”的管控,域名为“search.server.com”。
- 视频服务(W2):提供视频服务,部署于内网受到“S”的管控,域名为“multimedia.server.com”。
- 服务器(S):部署于公网,可以访问“W1”和“W2”,域名为“s.server.com”。
- 笔记本电脑(C):教学电脑,给学生在校外使用。
- 流代理(P):提供代理功能,能进行SSL卸载和加密,域名为“p.server.com”。
我们有此情景:“C”需要通过“S”,来访问“W1”搜索资料或访问“W2”观看教学视频。
在此之前都是在笔记本电脑上用“L2TP/IPSec”来与“S”建立安全连接,之后间接的通过“S”来访问“W1”和“W2”:
- 如上所示,“S”提供了“L2TP/IPSec”服务,且“C”与“S”建立了安全隧道,并通过隧道发送请求“https://search.server.com”以及“https://multimedia.server.com”,最终通过“S”分别访问到“W1”和“W2”。
由于上述方案在一些特殊状况下无法使用,因此我们考虑到使用“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”再也没法干预了。
实施¶
服务器(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),在笔记本上访问结果如下: