叠甲:本文仅记录博主在某些网络环境下遇到 Cloudflare Tunnel 无法连接的问题,以及通过 Zapret 改善连通性的技术过程,不涉及任何政治或敏感内容。
前言
博主昨天下午疯狂收到一台来自欧亚地区某神秘国服务器的告警,节点上的所有服务都炸掉了。一登录进去,发现是cloudflared连不上CF节点,进而导致所有基于CF Tunnel暴露的服务都无法被外网访问了。
其中,尝试更新cloudflared版本、更换为http2和quic的协议,都无法解决问题,基本确定是CF的节点被当地的IDC运营商封锁阻断了。
通过万能的Google和GitHub,最终成功借助DPI Bypass解决了本次问题,所以写一篇文章记录下来。
DPI Bypass
那么,什么是DPI呢?
DPI(Deep Packet Inspection)深度包检测,在一些企业/ISP里会用其来识别和阻止网络攻击等恶意内容,它不仅查看数据包的“外表”,还会深入数据包的“内部”,来判定数据包是否合规。
而DPI封锁,就比如说,你需要去寄一封信,DPI就是安检员,它不仅查看信封,还会拆开看信件的内容,当发现黑名单的内容时(比如CF Tunnel的连接特征),就直接把信丢碎纸机(丢包),或者给回你一张假的回信告诉你此路不通(发送RST重置连接)。
而DPI Bypass,顾名思义,就是绕过DPI封锁,主要是通过将“信件”(数据包)弄得乱七八糟,从而绕过DPI这一“安检员”的合规检测黑名单,进而放行。
我们本次用的Zapret就是一个专门用于实施DPI Bypass的工具箱,它本质是作用于你的主机/服务器,将数据包进行伪装,从而绕过DPI合规检测,成功放行。
根据Zapret文档,Zapret主要用到了下面几种技术:
切碎信件(TCP Split)
- 比如,将
Host: keke.su拆为Host: ke和ke.su,让DPI无法命中黑名单规则
乱序发送(Disorder)
- 比如,先发
ke.su再发Host: ke
扔烟雾弹(Fake Packets)
- 比如,在发真信之前发一封假信,以伪造正在访问合规的内容
改写格式(Header Modification)
- 比如,通过混淆大小写来修改信件的地址,试图让DPI无法识别原始意图
了解完基本原理后,我们可以开始尝试使用Zapret来解决CF Tunnel的阻断问题。
安装Zapret
首先,下载Zapret程序包:
wget -O - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4.tar.gz | tar -zx
然后,cd zapret-v71.4,执行./install_bin.sh,脚本将自动检测合适的预编译文件,将Zapret的二进制文件链接到指定目录。
接着,执行./install_prereq.sh,脚本会让你选择防火墙类型(iptables/nftables)以及是否使用IPv6等。博主这里选择的iptables,因为比较轻量,同时博主这台机器没有v6,所以不使用IPv6。
等待依赖安装完成,这时,可以执行./blockcheck.sh,一路回车即可,脚本会自动检测合适的Bypass策略。
最后,执行./install_easy.sh,并允许脚本复制二进制文件到/opt/zapret,记得选择开启nfqws,因为后面我们需要配置nfqws规则来解决CF Tunnel的连接问题。
配置规则
参考Cloudflare社区贴和GitHub的issue,我们首先cd /opt/zapret/。
然后,下载这两个bin文件,得到Google的quic和tls数据包特征:
有了数据包特征,我们接下来要告诉Zapret的NFQWS组件“如何干活”,所以,编辑规则nano /opt/zapret/config:
通过上述规则,Zapret将监视80/443/7844端口流量,然后只处理前9个数据包。当遇到匹配的数据包时,先连续发送Google的伪装数据包,再发送真实数据,从而绕过DPI检测。
最后,我们只需要sudo systemctl restart zapret重启服务即可。
通过sudo systemctl status zapret,我们可以看到处理规则已经正常应用:
然后,重启Cloudflared服务,发现已经可以正常连接上CF的服务器。
至此,教程结束~
