Some notes on ObfsUDP blocking in China / 关于 GFW 封锁迷雾通 UDP 的一些笔记

Some notes on ObfsUDP blocking in China

Geph uses two different underlying transports for its underlying protocol sosistab2:

  • ObfsUDP, an obfuscated UDP transport protocol with a somewhat ScrambleSuit-like handshake
  • ObfsTLS, an obfuscated TLS transport.

As particular astute Geph users might have notice, for the past year or so the Great Firewall of China has been blocking ObfsUDP traffic. This blocking is not immediate: once a new bridge is placed online, it takes generally a few hours before ObfsUDP traffic is blocked. In practice, this doesn't cause too big of a problem, since typically Geph bridges are recycled every few hours.

But since ObfsUDP is designed to be very difficult to identify as Geph traffic, this means that this a quite a serious problem. There must have been some sort of design oversight, since the GFW, given a few hours, can apparently identify obfsudp traffic quite accurately. (ObfsTLS traffic is left unmolested, so the attack clearly does not work by discovering bridge addresses)

For the past few weeks, I've been spending quite a bit of time investigating how the GFW is blocking ObfsUDP. I don't have many conclusions to share yet, but I plan to gradually document my journey in this thread.

A summary of how ObfsUDP works

Before we can talk about any hypotheses of how the GFW blocks ObfsUDP, it's helpful to quickly take a look at how ObfsUDP works, which can be found in its spec). Here are some important points:

  • An ObfsUDP server (such as a Geph bridge) has a unique public key, which legitimate clients know, but we assume the GFW does not know.
  • Before talking to the server, clients must execute a 4-way handshake with the server, which uses Diffie-Hellman (X25519) to establish a unique session key. Because session keys are unique, clients cannot spy on each other, unlike protocols like ShadowSocks.
  • After the handshake, application traffic is encrypted with the session key using ChaCha20-Poly1305.
  • The overall objective is for all packet contents to look uniformly random:
    • We assume ChaCha20-Poly1305 produces random-looking outputs, for an attacker who does not know the key.
    • Handshake packets have an additional layer of encryption, encrypted with the cookie, a symmetric key derived from the public key.
    • After the handshake, all packets are encrypted.

Two sorts of attacks and their defenses

Now, ObfsUDP overall attempts to defend against two kinds of attacks:

  • Passive detection: given a record of all packets on a network, some of which is ObfsUDP, it should be hard to pick out the latter from the former. Otherwise, the GFW can easily block ObfsUDP by simply identifying its packets and blocking them.
    • We defend against this by making all the packets look uniformly random.
  • Active probing: given a server that is suspected to be ObfsUDP, as well as a record of all packets going to and from that server, it should be hard to send fake traffic to the server and elicit responses that confirm that the server is ObfsUDP.
    • Probing "ex nihilo" is prevented because an attacker cannot forge any packets that will be validly encrypted, either with the cookie or a session key.
    • Probing by parroting previous captured legitimate packet is defended against by a sophisticated anti-replay mechanism, documented in the specs.

Current observations

As of right now, here's some observations:

  • Blocking seems to require some amount of traffic before it happens. It's hard to get an ObfsUDP server used by only one person in China blocked --- though sometimes that happens after heavy usage over several days. But blocking happens quickly when faced with the traffic levels of a small production Geph bridge (~100 Mbps continually over a few hours).
  • Adjusting ObfsUDP padding does not seem to affect blocking patterns, showing that packet sizes are probably not the signature that the GFW is matching against.
  • Packet traces do not show packets that look like replays --- namely packets from different IP addresses, separated by time, that contain the same contents. The few examples of duplicate packets are very close together and infrequent, and seem to be the result of some sort of network fault.

I am preparing some more targeting experiments though. I will post more replies here once I have more data.


关于 GFW 封锁迷雾通 UDP 的一些笔记

迷雾通(Geph)为其底层协议 sosistab2 使用了两种不同的底层传输方式:

  • ObfsUDP,一种带有类似 ScrambleSuit 握手过程的混淆 UDP 传输协议
  • ObfsTLS,一种混淆的 TLS 传输协议。

一些特别敏锐的迷雾通用户可能已经注意到,过去一年左右的时间里,中国的防火长城(GFW)已经开始封锁 ObfsUDP 流量。这种封锁并不是立即发生的:一旦新的桥接服务器上线,通常需要几个小时 ObfsUDP 流量才会被封锁。实际上,这并没有引起太大的问题,因为通常迷雾通的桥接服务器每隔几个小时就会更新一次。

但是由于 ObfsUDP 设计上非常难以被识别为迷雾通流量,这意味着这是一个相当严重的问题。肯定存在着某种设计上的疏忽,因为 GFW 在几个小时的时间后,显然可以相当准确地识别出 obfsudp 流量。(ObfsTLS 流量没有受到干扰,所以这种攻击显然不是通过发现桥接地址来进行的)

在过去的几周里,我花了不少时间研究防火长城是如何封锁 ObfsUDP 的。我还没有太多的结论可以分享,但我计划逐步在这个帖子中记录我的研究过程。

ObfsUDP 工作原理概述

在我们讨论防火长城如何封锁 ObfsUDP 的任何理论之前,了解 ObfsUDP 的工作原理是有帮助的,可以在规范中找到更多细节。以下是一些重要的点:

  • ObfsUDP 服务器(如迷雾通桥接)有独特的公钥。正常的客户端知道这个公钥,但我们假设 GFW 不知道。
  • 在与服务器通信之前,客户端必须与服务器执行一个四次握手过程,该过程使用 Diffie-Hellman (X25519) 来建立一个独特的会话密钥。因为会话密钥是独特的,客户端无法相互窥探,不像 ShadowSocks 那样的协议。
  • 握手之后,应用流量用会话密钥,使用 ChaCha20-Poly1305 算法加密。
  • 总体目标是使所有数据包内容看起来均匀随机
    • 我们假设 ChaCha20-Poly1305 对于不知道密钥的人来说,产生的输出看起来是随机的。
    • 握手数据包有额外的加密层,使用cookie加密,这是一个从公钥派生的对称密钥。
    • 握手之后,所有数据包都被会话密钥加密。

两种攻击及其防御

现在,ObfsUDP 总体上试图防御两种类型的攻击:

  • 被动检测:给定一个网络上所有数据包的记录,其中一些是 ObfsUDP,必须很难从前者中挑选出后者。否则,GFW 可以通过简单地识别其数据包并封锁它们来轻易封锁 ObfsUDP。
    • 我们通过使所有数据包看起来均匀随机来防御这一点。
  • 主动探测:给定一个怀疑是 ObfsUDP 的服务器,以及所有往来该服务器的数据包记录,必须很难发送假流量并引发确认流量是 ObfsUDP 的响应。
    • 由于攻击者无法伪造任何将被有效加密的数据包(无论是使用 cookie 还是会话密钥),因此「凭空」的探测是行不通的。
    • 通过复制之前捕获的合法数据包进行探测:通过一个复杂的防重放机制进行防御,该机制记录在规范中

当前观察

目前为止,这里有一些观察:

  • 封锁似乎需要一定量的流量才会发生。很难让只有一个人在中国使用的 ObfsUDP 服务器被封锁——尽管有时在连续几天的大量使用后会发生这种情况。但是当面对一个小型生产迷雾通桥接(大约 100 Mbps 连续几个小时)的流量水平时,封锁会很快发生。
  • 调整 ObfsUDP 中对包大小的混淆似乎不会影响封锁,表明数据包大小很可能不是 GFW 针对的特征。
  • 抓获数据包的记录后,没有发现看起来像重放的数据包——即来自不同 IP 地址、时间分隔的包含相同内容的数据包。少数重复的数据包非常接近且不频繁,似乎是某种网络故障的结果。

不过,我正在准备一些更有针对性的实验。一旦我有了更多数据,我会在这里回复更多帖子。

7 Likes

What if GFW staff download client, connect to bridges, and block ip by monitor which ip the client connect to?

大陆三家ISP一直都对UDP很不友好,作者应该知道这个情况。我在V2EX看到一篇帖文,讲了从2023年开始福建移动“更加人爲劣化國際訪問體驗”的事情,链接在这:https://www.v2ex.com/t/920909。另外V2EX上有不少讨论国内ISP对UDP访问Qos限速的帖子,不知道这些对作者有没有帮助。
@ nullchinchilla

其实联通还行,snowflake还能看油管

Everybody gets different bridges in Geph, so this easy attack is not possible :slight_smile:

这个跟 QoS 劣化不是一样的,这是全国性封一个 UDP 端口。

你好,我升级了plus,但是没用,所有节点都用不了,我要申请退款