纯NGINX实现TLS隧道

之前有提到过用Gost和FRP都可以实现TLS隧道,但是他们都使用golang实现。事实上,只用NGINX就能实现,而NGINX用c语言编写。

准备

在隧道两端的机器安装NGINX,可以查看我之前的文章《编译安装NGINX与使用》。同时,在编译安装的时候,需要在《编译安装NGINX与使用》一文的基础上追加stream模块和stream_ssl模块(configure的时候追加即可):

1
--with-stream --with-stream_ssl_module

注意:不要使用apt/yum等包管理工具安装NGINX。

TLS隧道配置

NGINX配置四层转发操作的时候使用stream模块(和HTTP模块并列),所以不要写错位置了,不要将stream写在HTTP代码块中。

TLS隧道加密端配置

编写如下配置:

1
2
3
4
5
6
7
8
9
10
stream {
server {
listen 1234;
proxy_ssl on;
proxy_ssl_protocols TLSv1.3;
proxy_ssl_server_name on;
proxy_ssl_name my.site;
proxy_pass 1.2.3.4:5678;
}
}

listen 1234告诉NGINX去监听本机1234端口的TCP连接。

proxy_ssl on告诉NGINX,上游服务具有一个TLS连接,NGINX会尝试与上游服务器进行TLS连接。

proxy_ssl_protocols TLSv1.3告诉NGINX,在连接上游TLS服务时,使用TLS1.3,。(注意:TLS1.3要求NGINX使用的OpenSSL库版本为1.1.1及以上,现在OpenSSL稳定版最新为1.1.1h。

proxy_ssl_server_name on告诉NGINX,在与上游TLS服务进行握手时,传递SNI信息。

proxy_ssl_name my.site告诉NGINX,使用my.site作为传递的SNI信息,否则使用proxy_pass中指定的host。

proxy_pass 1.2.3.4:5678告诉NGINX上游服务的位置。(注意:这里最好使用IP,如果一定要使用域名,必须在本机hosts文件中指定域名对应的IP,因为NGINX是静态联编的。

TLS隧道解密端配置

编写如下配置:

1
2
3
4
5
6
7
8
9
10
stream {
server {
listen 5678 ssl;
ssl_protocols TLSv1.3;
ssl_certificate /certs/my.crt;
ssl_certificate_key /certs/my.key;
# ssl_session_cache off; # 可选,我把TLS会话缓存关闭了。
proxy_pass 127.0.0.1:8888;
}
}

listen 5678 ssl告诉NGINX监听本机5678端口,并且开启TLS。

ssl_protocols指定了TLS版本。

ssl_certificate ssl_certificate_key指定了TLS证书与密钥。

proxy_pass指定了上游服务的位置(TLS隧道的终点)。

完成

在两端启动NGINX即可。

关于更多安全性设置可以参照文档:

ngx_stream_ssl_module

ngx_stream_proxy_module