This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
NaïveProxy 
NaïveProxy使用Chrome的网络堆栈来伪装流量,具有很强的抗审查能力和低可探测性。重用Chrome的堆栈也确保了性能和安全方面的最佳实践。
NaïveProxy可以缓解以下几种流量攻击:
- 通过HTTP/2中的流量复用缓解指纹识别/流量分类
- 通过重复使用Chrome的网络堆栈缓解对于TLS参数指纹识别
- 通过「应用前置」,将代理服务器隐藏在一个常用的前端(Caddy)与应用层路由后面)来防御主动探测
- 通过填充长度缓解基于长度的流量分析。
NaïveProxy的代码由一系列补丁组成,基于每个新版本的Chrome进行变形和重构。
架构
[浏览器 → Naïve (客户端)] ⟶ 审查者 ⟶ [前端 → Naïve (服务端)] ⟶ Internet
NaïveProxy使用Chrome的网络栈。所以防火墙截获的流量行为与Chrome和标准前端服务器(如Caddy、HAProxy)之间的常规HTTP/2流量是完全相同的。
前端的Caddy会将未经过认证的用户和主动探测流量重定向至后端的伪装服务器(或其他网站),使其无法检测到代理的存在,例如:
[探测] ⟶ 前端 ⟶ [本地伪装index.html]
从v84版本开始,用户可以使用包含naïve的caddy forwardproxy分支来代替单独的naïve服务端
下载
最简单的跨平台方式是从GitHub Releases下载编译好的二进制包
目前支援的平台有:Linux,Windows,Mac OS X以及OpenWRT
用户应始终使用最新版本,以保持签名与Chrome相同。
注意:在Linux上使用预编译好的二进制文件之前,必须先安装libnss3
配置
服务端
在服务器上, 用包含naïve的caddy forwardproxy分支编译并运行Caddy v2 (Golang v1.14+)
$ go get -u github.com/caddyserver/xcaddy/cmd/xcaddy
$ ~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy@caddy2=github.com/klzgrad/forwardproxy@naive
$ sudo setcap cap_net_bind_service=+ep ./caddy
创建/etc/caddy/Caddyfile
,加入以下内容(替换 <user>
& <pass>
)
:443, example.com
tls me@example.com
route {
forward_proxy {
basic_auth <user> <pass>
hide_ip
hide_via
probe_resistance
}
file_server { root /var/www/html }
}
:443
必须出现在文件头部,这个Caddyfile才可以正常工作。对于更高级的用法,可以考虑使用JSON进行Caddy 2的配置。
如果需要让caddy以守护进程的方式运行,请参考Run Caddy as daemon
客户端
在本地运行./naive
和以下config.json
,使naïve监听本地1080
的socks请求
./naive config.json
{
"listen": "socks://127.0.0.1:1080",
"proxy": "https://user:pass@example.com"
}
参见USAGE.txt以了解config.json
中的更多参数。另见性能优化。
自行编译
如果你不喜欢下载二进制文件,你可以自行编译NaïveProxy。
要求:
- Ubuntu (apt-get install): git, python2, ninja-build (>= 1.7), pkg-config, libnss3-dev, curl, unzip, ccache (optional)
- MacOS (brew install): git, ninja, ccache (optional)
- Windows (choco install): git, python2, ninja, visualstudio2017community. See Chromium's page for detail on Visual Studio setup requirements.
编译 (输出至 to ./out/Release/naive
):
$ git clone --depth 1 https://github.com/klzgrad/naiveproxy.git
$ cd naiveproxy/src
$ ./get-clang.sh
$ ./build.sh
改脚本会使用curl
从Google服务器下载所需要的工具。你可能需要为curl设置一个代理环境变量,例如:export ALL_PROXY=socks5h:/127.0.0.1:1080
。
FAQ
为什么不使用Go,Node等的TLS方案?
他们的TLS堆栈有明显的特征,可以轻易的被检测到。TLS参数通常含有非常大的信息量并且是可区分的。大多数客户端发起的流量来自浏览器,使Go,Node等定制的网络堆栈成为少数。
此前,Tor试图模仿Firefox的TLS签名,但仍然被识别并被防火墙封锁,因为该签名是Firefox的一个过时的版本。防火墙认为封锁该连结所附带的伤害比率是可以接受的。但如果我们使用的是最常用的浏览器的签名,阻止该连结的附带损害是不可接受的。
为什么不适用Go,Node等来获得更好的性能?
任何语言都可以用于高性能架构,但不是所有的架构都拥有高性能。
Go、Node等都可以很容易地实现1:1的连接代理模型即:每个用户连接都会创建一个与之对应的上游连接。在这种模式下,达到高性能的途径是减少在设置每个上游连接时的开销。为了实现这个目标,人们开始重新发明他们自己的0-RTT加密协议**(他们不该这么做)**,因为TLS要在握手中花费几个来回,要[正确设置0-RTT会很痛苦](https://tools.ietf.org/html/rfc8446#section-8),所以TLS被淘汰了。然后人们开始关注低级别(如TFO)优化。
与此同时,谷歌已经完全删除了Chromium中的TCP Fast Open代码(他们在2014年撰写了TCP Fast Open的RFC)。Google给出的书面解释是:
We never enabled it by default, and have no plans to, so we should just remove it. QUIC also makes it less useful, and TLS 1.2 0-RTT session restore means it potentially mutates state.
我们从来没有默认启用它,也没有计划启用,所以我们应该直接删除它。 QUIC也使得它不那么有用,而TLS 1.2 0-RTT会话恢复意味着它可能会改变状态。
而谷歌从未默认启用TCP快速打开的真正原因是因为它被「中间商」拖累,导致TFO从未真正的发挥作用。
在Linux的内核中,有一个名为 tcp_fastopen_blackhole_timeout_sec
的系统控制参数,每当一个SYN数据包被丢弃,TCP Fast Open就会被丢进黑洞(从一小时开始,以指数形式增加,使其几乎没有用处)。目前为止,TFO仅占互联网流量的0.1%,所以使用它实际上使你很容易被发现
对谷歌来说,在1:1的连接模式下,牺牲安全和互操作性为代价来实现零延迟操作是行不通的,这也是为什么谷歌在HTTP/2中追求连接持久性和1:N连接复用,以及在QUIC中对HTTP/TLS/TCP进行更彻底的修改。
在1:N的连接模式中,建立第一个连接的成本可以被分摊掉,而之后的连接不需要花费任何成本就可以建立,没有任何安全或稳定性的损失,因此争夺零连接延迟也变得不重要
Chromium已经造好了这个轮子,并且在Chromium中得到了应用和考验。在用上述语言从头开始做同样的事情就不那么容易了。
为什么不重新研发加密算法?
如果你真的想手搓了自己的密码,看看Shadowsocks发生了什么。(它能加密,但不能认证,使其可以被主动探测到,在尝试用「胶带」修复后产生了更多漏洞)。
为什么不直接使用浏览器的HTTP/2代理?
你可能会想,既然NaïveProxy重用了Chrome的网络栈,为什么不直接使用Chrome呢?当然可以,在没有NaïveProxy的情况下,你可以得到NaïveProxy的80%的功能(TLS、连接复用、应用前置),这也是无法将NaïveProxy与正常流量区别出来的原因。只需将您的浏览器直接指向Caddy作为HTTP/2或HTTP/3转发代理。
但由于TLS握手中缺乏混淆和可预测的数据包大小,这种设置很容易受到基本的流量分析。"TLS-in-TLS "隧道的祸根是这种组合与任何正常的协议都有很大的不同(没有人连续做两次握手),而且TLS握手的记录大小是可预测的,不需要机器学习就可以检测。
浏览器在代理连接设置过程中会引入一个额外的1RTT延迟,在CONNECT请求后等待200响应,产生1RTT,这是没有必要的。NaïveProxy所进行的HTTP快速连接类和TFO类似即:在CONNECT后立即发送后续数据。
流量混淆、HTTP快速连接和自动认证是NaïveProxy提供的最后20%的也是最关键的部分。这些都不能在Chrome内部通过扩展程序实现,因为它们不能直接访问socket。而NaïveProxy只提取了Chromium的网络堆栈,来编译一个小的二进制文件(仅完整的Chrome的4%)。
如果你不需要最好的性能,而且未经混淆的TLS-in-TLS
在某种程度上仍然对你有效,你可以继续使用Caddy代理服务器搭配你的浏览器。
另外,你可能要在每次打开浏览器时都要输入代理的密码。NaïveProxy则会自动发送密码。
为什么不支援「CDN」
以Cloudflare为例:"禁止将服务用于提供视频(除非单独购买付费服务)或比例过大的图片、音频文件或其他非HTML内容。" 在这种情况下,代理流量肯定是属于明文禁止的。