在之前的文章《纯NGINX实现TLS隧道》中,我们用纯NGINX实现了纯c语言的高效TLS隧道。在这篇文章中,我们将实现类似于之前文章《隐藏在站点下的NGINX前置WSS隧道建设》中的效果,即正常访问域名会被提供正常的网页服务,而使用特定手法(前文为使用特定的路径访问,本篇文章使用NGINX stream map)连接则可以使用到隐藏的服务,而两种访问因为都使用同一端口,使用同一证书,故而很难被探测者/攻击者察觉网站背后的服务。
前提条件
假设你原本有如下的网站配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| http { server { listen 80; server_name my.site; if ( $host != "my.site" ) { return 403; } return 301 https://my.site$request_uri; } server { listen 443 ssl; server_name my.site; ssl_protocols TLSv1.3; ssl_certificate /etc/certs/cert.pem; ssl_certificate_key /etc/certs/key.pem; if ( $host != "my.site" ) { return 403; } location / { root /etc/www; index index.html; } } }
|
TLS隧道解密端
修改刚刚的NGINX配置为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| stream { map $remote_addr $backend { 1.2.3.4 127.0.0.1:33443; default 127.0.0.1:22443; } server { listen 443; proxy_pass $backend; } server { listen 33443 ssl; ssl_protocols TLSv1.3; ssl_certificate /etc/certs/cert.pem; ssl_certificate_key /etc/certs/key.pem; proxy_pass 127.0.0.1:8888; } }
http { server { listen 80; server_name my.site; if ( $host != "my.site" ) { return 403; } return 301 https://my.site$request_uri; } server { listen 22443 ssl; server_name my.site; ssl_protocols TLSv1.3; ssl_certificate /etc/certs/cert.pem; ssl_certificate_key /etc/certs/key.pem; if ( $host != "my.site" ) { return 403; } location / { root /etc/www; index index.html; } } }
|
其中,1.2.3.4
是TLS隧道加密端的IP。
这样设置之后,在TLS隧道加密端访问本机443端口时,会被分流至33443端口以建立TLS隧道;而在其他IP连接(默认情况)时,会被分流至22443的HTTPS Web服务。
TLS隧道加密端
1 2 3 4 5 6 7 8 9 10
| stream { server { listen 8888; proxy_ssl on; proxy_ssl_protocols TLSv1.3; proxy_ssl_server_name on; proxy_ssl_name my.site; proxy_pass 5.6.7.8:443; } }
|
优点
- TLS隧道服务变得隐秘。探测者/攻击者除非使用规定的IP访问443端口,不能访问到TLS隧道,而只能接触到Web服务。
- 效率高,不用担心性能不足导致的带宽不足、延迟波动等问题。
缺点
尽管连接隧道与正常访问Web服务使用相同的端口、相同的证书,但是其不同的TLS Client Hello指纹最可能会出卖我们。
TLS隧道加密端使用的是OpenSSL库,并且已经指定TLS版本为TLS1.3,这使得其发送的TLS Client Hello中带有的加密套件具有很明显的特征,与普通浏览器(如Chrome)发起的TLS Client Hello中带有的加密套件明显不同(后者占整个互联网TLS流量的26%左右)。