第一幕 · 伪装者的困境:TLS 指纹与微观审查
2018 年前后,中文网络审查迎来了划时代的质变。防火长城部署了基于深度学习与被动指纹提取的精密系统,开始对所有经过出境网关的 TLS 连接进行极其严苛的微观审视。其中最具代表性的便是 JA3 算法——它通过记录客户端在 Client Hello 握手包中声明的 TLS 版本、密码套件清单(Cipher Suites)、扩展字段(Extensions)及其协商顺序,为每一个发起请求的程序打上独特的指纹。
当时主流的翻墙工具(如基于 Go 语言标准库 crypto/tls 构建的各种核心)遭遇了毁灭性的打击。Go 语言默认的 TLS 握手特征极其鲜明且罕见于普通商业浏览器,审查设备只需在海量出境流量中过滤出“使用了 Go 语言 TLS 签名却频繁访问境外未知网站”的流量,即可施加精准的丢包与端口阻断。一时间,各大开源项目疲于奔命地在代码里手动调整密码套件顺序,然而现代浏览器的网络行为极其繁复庞大,任何一个极细微的握手偏差或时序异常都会被审查者的机器学习模型立刻捕获。[1]
第二幕 · 降维打击:直接潜伏进 Chromium 腹地
在这场看似永无止境的猫鼠游戏中,klzgrad 展现出极其深刻的敏锐洞察与决绝魄力:既然任何对浏览器的“模仿”终究都会因为细节疏漏而被识破,那为什么不直接把代码写进真实的浏览器里面?
2019 年初,klzgrad 正式公布了 NaïveProxy。他没有像常规项目那样轻便地调用第三方网络库,而是采用了一种极其硬核且充满工程难度的做法:直接拉取庞大复杂的 Google Chromium 代码库,将代理客户端与服务端的转发逻辑作为补丁,深度嵌入并编译在 Google Chrome 官方核心网络栈——Cronet 之中。这一决策堪称抗封锁史上的“降维打击”。当 NaïveProxy 发起连接时,它所输出的不仅仅是形似 Chrome 的握手包,它本身就是真正的 Chrome 内核代码在运行。从套件顺序、GREASE 假字段填充、ALPN 协商到底层的 TCP 拥塞控制与证书校验,审查系统在二进制层面上根本无法区分这究竟是一个普通的海外网页访问,还是一条正在翻墙的加密隧道。[2][3]
第三幕 · 极致的防御艺术:Padding 与防主动探测
不仅是在握手阶段做到真假难辨,klzgrad 更在传输层与服务层实施了一系列严密的抗审查防御准则。为了防御基于数据包长度与传输节奏的侧信道指纹分析,NaïveProxy 创造性地引入了应用层长度填充(Application-Layer Padding)机制,利用 HTTP/2 协议原生的 Padding 机制随机打乱数据帧大小,彻底抹平了代理流量在交互时特有的数据包特征。
而在服务端防御层面,NaïveProxy 强制推行前后端职责解耦:前端必须通过真实合规的工业级 Web 服务器(如配备了 forwardproxy 模块的 Caddy)承接入站流量。如果审查方使用探针伪装成客户端向该端口发送非认证的探测请求,Caddy 将表现得与世界上任何一个完全合规的标准网站一模一样,直接返回真实网页或正常 HTTP 状态码,使任何主动探测技术彻底失效。[2]