本文以「gost」为例,基于nginx前置及节点已有其他服务运行(假定为非官方chat代理)的假设,基于nginx分流策略,探讨降低代理服务可探测性的基本方法。
1.使用systemd管理代理服务
使用nohup等方式将gost置于后台运行无法实现对代理服务的基本管理。一般使用systemd对gost进程进行守护管理,创建并加载systemd服务描述文件/etc/systemd/system/gost.service如下:
[Unit] Description=GOSTv3-Server of GO simple tunnel Documentation=https://gost.run/ After=network.target [Service] Type=simple ExecStart=/usr/local/bin/gost/gost -L ws://username:password@:8443 Restart=always [Install] WantedBy=multi-user.target
详细的systemd服务文件配置请见博文「基于systemd实现服务开机自启动的方法」。
2.几项https://github.com/go-gost/gost可选措施
2.1 强制https
强制https可以防止因疏忽或“省事”心理而造成的安全问题。在nginx配置文件http块中增加相应配置即可。
server { listen 80; server_name chat.example.com; if ( $host != "chat.example.com" ) { return 403; } return 301 https://$server_name$request_uri; }
2.2 反爬虫
这里也是添加在nginx配置文件的对应server块中。
if ($http_user_agent ~* "360Spider|JikeSpider|Spider|spider|bot|Bot|2345Explorer|curl|wget|webZIP|qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot|NSPlayer|bingbot"){ return 403; }
2.3 包含特殊字符的验证信息
这是gost工具提供的功能,当用户验证信息中包含特殊字符,username:password方式无法正常工作,就需要采用auth参数了。
a=$(echo -n username:password | base64) gost -L relay+ws://:8443?auth=${a}
gost v3新增了认证器概念,可以看成是v2.x secrets的升级。认证器包含一组或多组认证信息。服务通过认证器可以实现多用户认证功能,但认证器仅支持配置文件设置。
3.nginx配置
3.1 基于应用层的协议支持
以下PathDiversion可使用系统uuid替换。
p=$(cat /proc/sys/kernel/random/uuid) gost -L ws://:8443?username:password@:8443?path=${p}
http中相应的server块添加如下代码:
location /PathDiversion { proxy_redirect off; proxy_pass http://127.0.0.1:8443; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; }
在不使用auth参数的情况下,gost.service文件中对应的gost服务端运行命令改为:
gost -L ws://username:password@:8443?path=/PathDiversion #tls加密由nginx通过https完成,无需重复加密
此时,客户端转发设置应采用wss并转出为socks5,具体命令为:
gost -L socks5://:10088 -F wss://chat.example.com:443?path=PathDiversion
在使用http/https/http2代理且开启用户验证的前提下,gost工具支持探测防御,通过probeResistance配置“回落”,包括code、web、host、file等方式。
gost -L=http://gost:gost@:8443?probeResistance=code:403 gost -L=http://gost:gost@:8443?probeResistance=web:example.com/page.html gost -L=https://gost:gost@:8443?probeResistance=host:www.example.com:8080 gost -L=http2://gost:gost@:8443?probeResistance=file:/send/to/client/file.txt
3.2 基于传输层的协议支持
此处假定节点还安装了某非官方ChatGPT代理服务,域名为chat.example.com。在确认已安装stream模块的前提下,
老E推荐最简单的实现方式,即在nginx.conf文件中,不对http块进行修改(不增加路径分流的location块),在http块之前增加stream块内容。需要注意的是,此方案下需要区分stream和http端口,nginx在已有stream模块端口转发配置的情况下,不会再去匹配、执行同端口下的http/https服务配置。同时,本地服务的端口转发/反向代理可不必使用tls。
stream { upstream transend { server 127.0.0.1:8443; #gost—_L_port } server { listen 8080; #tcp #listen 1443 ssl reuseport; #tcp+tls proxy_pass transend; #ssl_certificate path/to/your/crt; #ssl_certificate_key path/to/your/key; #ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; #ssl_ciphers HIGH:!aNULL:!MD5; #ssl_prefer_server_ciphers on; } }
如果确有端口复用的需求(代理节点绝大部分情况下没有这样的需求),可以使用sni分流,在http配置块前增加stream块的核心配置内容如下:
stream { map $ssl_preread_server_name $stream_map { chat.example.com chat; other.example.com other; } upstream chat { server 127.0.0.1:443; } upstream other { server 127.0.0.1:8443; } server { listen <public_ip>:443 reuseport; proxy_pass $stream_map; ssl_preread on; } }
此时,http server需要增加http2优化,其他不变,nginx会载入http_v2_model模块。核心配置内容调整如下:
server{ listen 127.0.0.1:443 ssl http2; ... #删除location }
此时,使用gost等隧道工具,可以此为基础使用socks5等协议与客户端建立数据传输通道。如持有路径分流的“执念”,可以尝试新增stream upstream块和http server块,新增的server location中的proxy_pass与新增的upstream配置名称匹配,新增upstream中的端口与server块中listen端口匹配。
文章评论