Skip to content

简体中文

Error404 edited this page May 9, 2021 · 3 revisions

NaïveProxy build workflow

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内容。" 在这种情况下,代理流量肯定是属于明文禁止的。