墙中之墙:中国地区性审查的兴起

墙中之墙:中国地区性审查的兴起

https://gfw.report/publications/sp25/zh/

这些结果尤其值得注意,因为它们显示了远程测量无法触发地区性防火墙,更重要的是,揭示了 GFW 的不对称行为。虽然从中国境内发起的连接平均有 479 个域名被封锁,但从中国境外发起的连接只有 411 个域名被封锁。这种差异表明 GFW 对源自中国境内的流量执行不同的封锁列表。直到最近,人们仍普遍认为 GFW 是对称运作的,无论流量方向如何,都会触发相同的封锁列表。然而,最近的研究表明这种假设是不正确的 [9],我们在此的发现与其观测结果一致。

我们注意到 GFW 和河南防火墙都在不同程度上表现出不对称的封锁。如图4(a)所示,虽然离开河南的流量受到地区性防火墙(由内向外)的影响,但进入河南的入站流量(由外向内)完全不会触发地区性防火墙。这与 GFW 形成对比,GFW 是双向的(但其行为根据查询的域名而表现出不对称性)。

图4(b) 提供了一个清晰的例子来说明这种行为。在我们的案例中,当一个 SNI 值为 docker.com 的 TLS ClientHello 从中国境内发送时(由内向外),GFW 会通过三个 TCP RST 数据包触发封锁。然而,当相同的 TLS ClientHello 从中国境外发送时(由外向内),GFW 不会触发任何封锁。另一方面,当发送带有 SNI 值 youtube.com 的 TLS ClientHello 数据包时(在此示例中),无论数据包是从中国境内还是境外发送,GFW 都会在两种情况下触发封锁。这种行为表明存在一个明显的域名封锁列表,这些域名仅在从中国境内访问时才会被 GFW 审查。

图4: (a) 河南防火墙不审查进入河南的入站 TLS 或 HTTP 流量,这与 GFW 采用的双向审查形成对比。 (b) GFW 的 TLS 和 HTTP 审查机器检查进出中国的双向流量;然而,某些域名仅在从中国境内访问时才被审查。在此示例中,虽然从中国境内发送带有 SNI 值 docker.com 的 TLS ClientHello 可以触发 GFW 发送三个 TCP RST 数据包,但从中国境外发送时则不会触发任何封锁。

在我们检测地区性审查的实验中,我们无意中发现了 GFW 运作机制的一个重要方面,而这直到最近才被记录下来 [9]。新观察到的 GFW 和地区性防火墙共有的不对称性,表明审查测量需要由内向外的测量,以全面捕捉审查的范围和细微差别。仅仅依赖由外向内的远程测量,正如其他许多研究中常见的那样,则无法提供此类审查机制的全面情况。

为了进一步证实 GFW 的不对称行为,我们提供了一个域名列表,这些域名仅在从中国境内发送 TLS ClientHello 消息时被封锁,如表2所示。在我们的实验中,10,000 个域名中有 68 个在从中国境外测试时未触发任何审查,仅在从中国境内探测时才被封锁。这些域名包括流行的网站,如 google.com、nyt.com 和 docker.com。该列表提供了具体的证据,证明 GFW 根据流量来源和相关域名选择性地执行其封锁列表。

表2:仅能从中国境内发送 TLS ClientHello 消息时触发 GFW 封锁的部分域名示例。截至 2024 年 7 月 10 日,这些域名在从中国境外向境内发送时未触发审查。在我们测试的 10,000 个 Tranco 热门域名中,有 68 个域名仅在由内向外发送时触发封锁,没有域名仅在由外向内发送时触发封锁。

binance.com godaddy.com note.com cdninstagram.com google.com nyt.com docker.com google.com.hk tiktokcdn.com gmail.com linktr.ee torproject.org

自 2023 年 10 月以来,我们进行了一系列实验来分析审查设备的特征,并理解中国防火长城(GFW)与河南地区性审查设备之间的差异。在本节中,我们将回答几个研究问题:地区性审查设备位于何处?哪些数据包可以触发河南 SNI 防火墙?河南防火墙监控哪些端口?注入的TCP RST 包是否具有特定的指纹?河南防火墙是否会引发残余审查?

如前所述,我们针对地区性和国家级两种防火墙的具体特征制定了一套测量方法。为了精确评估每种防火墙的影响,我们的方法单独隔离并分析这两个系统。这种基于我们初步观察设计的测量方法,是我们进行全面测量实验的基础。我们的测量方法概述如下。

获取测量点。 我们总共在中国郑州(河南)通过China VPS(AS 4837)获取了 10 个测量点,在广州、北京和上海通过腾讯云(AS 45090)获取了两台 VPS,以及在美国旧金山通过 Akamai 的 Linode(AS 63949)获取了两台 VPS。位于广州、北京、上海和旧金山的 VPS 作为水槽服务器,被设置为监听在从 1 到 65535 的所有端口以接受 TCP 连接,但不向发送方发回任何TCP载荷数据。我们所有的机器都运行 Ubuntu 22.04,并使用 IP2Location [62] 数据库验证了它们宣称的位置。我们在表1中总结了我们实验的时间线和每个实验使用的测量点。

在 VPS 上丢弃传出的 RST 数据包。 我们在客户端和水槽服务器上都配置了 iptables 规则来丢弃所有传出的 RST 数据包。这种配置确保客户端收到的任何 RST 数据包都一定是由中间设备伪造的。

触发基于 TLS SNI 的审查。 我们通过发送在 SNI 字段中包含可能被审查域名的 TLS ClientHello 来触发审查。由于水槽服务器被配置为不发送任何带有载荷的数据包,并且在观察到 FIN 或 RST 数据包之前不切断连接,我们预期收到的任何 RST 数据包都一定是防火墙注入的伪造包。如果包含该域名的 TLS 连接收到了 RST 数据包,我们就将该域名标记为被审查。

触发基于 HTTP Host 的审查。 为了触发 HTTP 审查,我们发送了 HTTP GET 请求,请求的 Host 头部包含被禁止的域名:


GET / HTTP/1.1\r\nHost: example.com\r\n

虽然我们后来发现河南防火墙不需要完整的 TCP 握手来触发封锁,但在发送 HTTP 请求之前,我们仍然完成了 TCP 握手,这使得我们对于河南防火墙的测试方法与对 GFW 的测试方法一致。如果包含该域名的 HTTP GET 请求收到了 RST 数据包,我们就将该域名标记为被审查。

隔离河南防火墙。 为了区分河南防火墙和 GFW 的响应,我们识别了每种防火墙的独特指纹。先前的工作记录了 GFW 在观察到包含禁止的SNI的 TLS ClientHello 消息时,会向连接的两端注入最多三个 RST+ACK 数据包来中断连接 [263]。相比之下,河南防火墙仅向连接的客户端注入单个 RST+ACK 数据包。此外,河南防火墙的 RST+ACK 数据包包含载荷,使其易于与 GFW 的响应区分开来。我们将在第4.4节中对此进行更详细的介绍。

最后,我们从河南的测量点向广州、北京和上海的服务器发送探测包,以确保我们的流量不会路由到中国境外(在边境可能会遇到 GFW),但仍然受到河南地区性防火墙的影响。

局限性。 我们在河南省的测量仅限于单个自治系统(AS),即中国联通(AS 4837),这是因为在中国获取可用于审查测量的测量点存在困难,并且需要考虑伦理问题。因此,我们的实证结果仅限于这家互联网服务提供商(ISP)的网络环境。节点的缺乏限制了我们确认或描述河南其他 ISP 或 AS 审查的能力。

虽然用户报告表明河南的 ISP 采用了地区特定的审查,但据报告审查的实施方式有所不同 [64]。例如,Github 用户 5e2t 报告称,中国移动河南公司审查其在蜂窝数据网络上的流量,并且能够重组间隔很近的 TCP 数据包 [64],这与我们在第4.3节中观察到的中国联通河南的行为不同。因此,我们的结果应被理解为仅反映了中国联通河南的审查情况,而不一定代表全省所有 ISP 的审查情况。

河南防火墙是否对流量进行抽样监控和审查? 据观察,一些审查者有时仅监控和审查一部分流量,这可能是为了减少其审查设备的计算负载 [15 §6.3]。然而,我们没有观察到河南防火墙有任何流量采样或概率性封锁行为。我们观察到河南防火墙持续封锁其封锁列表上的域名。我们连续发送了 1,000 个包含被禁止域名的 ClientHello 消息,每个请求都使用一对不同的端口进行发送,并带有微小的间隔。我们建立的每个连接都收到了 TCP RST 数据包,这表明河南防火墙对被禁域名的封锁触发率为 100%。

河南防火墙监控哪些端口? 先前的工作表明,GFW 的 TLS ESNI 审查中间设备监控所有端口,即 1-65535 [10]。为了测量河南防火墙,我们向位于中国广州的水槽服务器的所有端口发送了带有已知被禁 SNI 的 TLS ClientHello 消息。我们发现,与 GFW 类似,河南防火墙监控流向任何 TCP 端口号(范围在 1 到 65535 之间)的 TLS 流量。

河南防火墙是双向的吗? 由于在受审查区域获取测量点存在难度和限制,研究人员通常选择从外部向内进行测量,而不是从内部向外测量。特别是在中国,研究 GFW 的工作 [349] 使用了中国境外的测量点,因为 GFW 具有双向性。然而,正如第3节所述,从中国境外发送探测不会触发河南防火墙,因为河南的防火墙只审查离开河南的流量。如图3所示,我们通过在河南节点和中国其他地区的节点之间发送包含 Tranco 列表 [60] 5YZ7N 中不同 SNI 值的 TLS ClientHello 消息来测试这一点。我们发现只有离开河南的流量被河南防火墙封锁。先前的工作也观察到 GFW 存在类似的不对称封锁行为 [910]。

在本节中,我们研究河南防火墙和 GFW 的流量解析逻辑。我们进行实验以检查触发河南防火墙和 GFW 审查的 TCP 握手要求。我们还使用 DPYProxy [65] 来测试这两种防火墙的 TCP 和 TLS 重组能力,以及是否存在残余审查。我们在表3中总结了我们的发现。

表3:GFW 和河南防火墙的流量解析逻辑。河南防火墙似乎是无状态的,并且在应对不同网络流量时不如 GFW 健壮。

GFW 河南防火墙 需要看到 SYN ✓ ✗ 需要看到 SYN+ACK ✗ ✗ 支持TCP重组 ✓ ✗ 支持TLS重组 ✗ ✗ TCP 头部长度要求 任意 仅 20 字节

TCP 握手完整性要求。 网络中间设备的设计者通常需要在流量解析逻辑的健壮性和效率之间进行权衡。例如,由于互联网的非对称路由特性,以及河南防火墙和 GFW 并非总是客户端或服务器的直接邻居(如表5所示),网络中间设备可能只能观察到单向的流量。这种特性常常使得中间设备的设计者放弃使用完整的 TCP 三次握手来追踪 TCP 连接并进行审查。在 2024 年 10 月 10 日,我们从河南的测量点测试了河南防火墙和 GFW 对 TCP 握手完整性的要求。我们发送了一个 TCP 数据包,其载荷是一个包含被禁止域名 011.com 作为 SNI 的 TLS ClientHello 消息,发送该数据包之前:1) 我们发送了来自客户端的 SYN 数据包,或 2) 我们发送了来自客户端的 SYN 数据包和来自服务器的 SYN+ACK 数据包,或 3) 我们根本没有发送任何其他数据包。

表3所总结的,虽然 GFW 需要观察到来自客户端的 SYN 数据包(但不需要来自服务器的 SYN+ACK 数据包)才能触发审查 [9],但河南防火墙不需要观察到任何 TCP 握手数据包即可被触发。

TCP 分片。 TCP 分片能够将较大的 TCP 载荷分割成较小的载荷。在规避审查的背景下,将 TLS ClientHello 消息分割成多个 TCP 分段已被用于绕过不对数据包进行重组的无状态审查者。然而,我们确认 GFW 执行 TCP 重组,因此是有状态的。另一方面,我们发现河南防火墙不进行 TCP 重组,因此可以通过将 ClientHello 的 TCP 载荷分割成多个 TCP 分段(SNI 分布在这些分段之间)来绕过它。我们通过从河南的测量点向广州的 VPS 发起一个带有被禁止 SNI 的 TLS 连接,并将 ClientHello 分割成两个分段(第二个分段包含被禁止的域名)来测试这一点。我们观察到,虽然完整的 ClientHello 消息被河南防火墙封锁,但如果第一个分段中不包含完整的 SNI 扩展,则可以绕过河南防火墙。

TLS 分片。 虽然 TCP 分片长期以来被用来绕过无状态审查者,但 TLS 分片的使用直到最近才由 Niere 等人 [65] 分析并在他们的 DPYProxy 工具中实现。在 TLS 消息被封装到 TCP 分段之前,它首先被包含在一个称为 TLS 记录的结构中。鉴于 TLS 消息的最大大小超过了 TLS 记录的最大允许大小,TLS 标准允许将 TLS 消息分割到多个 TLS 记录中。Niere 等人 [65] 发现 GFW 不执行 TLS 重组,因此可以通过将 TLS ClientHello 消息分片到多个 TLS 记录中(其中 SNI 被分割到同一 TCP 载荷内的多个 TLS 分段中)来绕过它。我们确认,截至 2024 年 4 月 4 日,河南防火墙和 GFW 都不执行 TLS 重组,因此可以通过 TLS ClientHello 分片来绕过它们。

TCP 头部长度必须为 20 字节。 TCP 头部的第 13 个字节的前四个有效位表示 TCP 数据偏移量,它指定了 TCP 头部的长度(以 32 位字为单位)。当没有 TCP 选项存在时,TCP 数据偏移字段的最小值为 5 个字(20 字节),最大值为 15 个字(60 字节)。

我们发现河南防火墙要求 TCP 头部长度必须正好是 20 字节才能正确解析和封锁 TLS ClientHello 或 HTTP 请求消息。我们在 2024 年 10 月 17 日,通过从河南的测量点向广州的水槽服务器发送包含被禁止消息(例如,带有被禁止 SNI 011.com 的 TLS ClientHello 消息)并设置不同的 TCP 选项来进行测试。在改变 TCP 头部长度的同时,我们确保 TCP 选项始终是四字节的倍数,以符合 TCP 头部的 32 位字对齐要求。我们测试的 TCP 选项包括常见的选项,如最大分段大小(MSS)、窗口缩放、时间戳、选择性确认许可(SAckOk)、无操作(NOP)、选项列表结束(EOL),以及不常用的自定义 TCP 选项。我们发现,只要设置了任何 TCP 选项,河南防火墙就不会封锁连接。

一个自然提出的假设是,河南防火墙不解析 TCP 头部中的 TCP 头部长度字段,并错误地假设 TCP 头部长度始终为 20 字节。这样,当 TCP 头部因 TCP 选项而超过 20 字节时,它会将 TCP 选项视为 TCP 载荷的一部分,从而无法识别完整的 TLS ClientHello 或 HTTP 请求消息。然而,我们证伪了这一假设,并确认河南防火墙确实解析了 TCP 头部长度字段。具体来说,我们首先发送了带有被禁止 SNI 011.com 且 TCP 头部未设置任何 TCP 选项的 TLS ClientHello 消息,并确认该消息被河南防火墙封锁。如果河南防火墙不解析 TCP 头部长度字段,那么无论我们在 TCP 头部中放入什么 TCP 头部长度值,该消息都应该被封锁。我们将 TCP 头部中的 4 位 TCP 头部长度字段更改为所有 24 种可能的值(从 0 到 15),并为每个 TCP 数据包重新计算了正确的 TCP 校验和,发现河南防火墙仅在 TCP 头部长度值为 5 个字(20 字节)时才封锁连接。该实验表明河南防火墙确实解析了 TCP 头部中的 TCP 头部长度字段,但有一个条件,即仅在 TCP 头部长度为 20 字节时才封锁连接。

虽然我们无法确定此条件背后的意图——也许是审查者的疏忽——但这引出了一个重要问题:由于此条件的存在,有多少真实世界的流量避免了被检测?我们在美国的一所大学网络进行了测试。具体来说,我们使用 Retina [66] 在 2024 年 10 月 31 日下午 3:56:14 到 4:56:14(UTC–7)的一个小时内捕获了校园网络上所有流量的 TCP 头部长度字段。总共,我们收集了 231 亿个 TCP 数据包和 50 亿个 TLS 数据包。如图5所示,只有 22% 的 TCP 数据包头部长度为 20 字节,只有 19% 的 TLS 数据包头部长度为 20 字节。这一结果表明,河南防火墙可能只能审查大约 20% 的目标连接。

图5:2024 年 10 月 31 日在一所大学网络上捕获的一小时内所有 TCP 和 TLS 数据包的 TCP 头部长度字段分布。总共捕获了约 231 亿个 TCP 数据包和 50 亿个 TLS 数据包。只有 22% 的 TCP 数据包头部长度为 20 字节,而只有 19% 的 TLS 数据包头部长度为 20 字节。这一评估结果表明,河南防火墙可能只能审查大约 20% 的目标连接。



Read Next page

Report Page