网络封锁与反封锁
前言
近日, 俄罗斯政府将 discord 进行了网络封锁, 其国内用户不再能直接使用该软件, 除非使用科学上网软件或者将网络流量进行一些伪装.
在搜集学习了一些相关资料后, 今天将一些读后所得记录于此, 以免以后忘掉.
正文
不同国家地区封锁的范围和策略并不相同。以我国为例, 除了国家层面大名鼎鼎的GFW外, 小到一些运营商或者校园网络都可能进行一些网络流量干扰或阻断.
干扰的方式一般是对特定网络流量进行限制. 这些流量可能是以下条件的单独一项或者多项的组合:
type1.访问特定目的IP地址 type2.访问特定目的端口 type3.访问特定 URL 或 SNI type4.报文真实 payload 满足某些特征
其中, type1 和 type2 的封锁是比较刚性, 网络监管者可以很容易地就从报文中提取这些字段, 因此只能使用 proxy 绕过网络监管者才能突破封锁.
而 type3 的识别则需要网络监管者对 TCP 的 payload 进行识别, 不过由于 TLS 也是标准一些, 且包含 SNI 信息的 TLS client hello 报文是明文传输, 因此监管者要得到这些信息也不难。
要绕过 type3 的封锁, 使用 proxy 是一个可选方案. 不过鉴于监管者可能会扫描 TCP 连接建立后的前N个包, 更安全的做法是将 TCP 建立连接后的数据部分整个做一层加密, 这样网络报文就看不到 URL 或者 SNI 的明文信息.
当然, 如果已经摸清楚封锁的规律, 就可以采用更轻松的办法。以本次俄罗斯地区对 discord 的封锁为例, 使用开源软件 zapret 提供的方案就可以绕过运行商对登录流量的封锁.
zapret 采用的方案是在向 Discord 服务器建立 TCP 连接后, 发送若干个 fake TLS client hello 握手报文, 这些报文的 SNI 是 www.google.com, 但其 TCP 序号不在发送窗口之内. 随后再发送正长的 SNI 为 discord 相关域名的正常的 TLS 握手包.
这样做可行的原因是, 运营商只会检测了前 N 个 TCP 数据报文的内容, 当其发现 SNI 是 www.google.com, 便将这条 TCP 流视为合法的流, 随后就发行该流的后续报文, 不再进行审查
而由于这些伪造报文的 TCP 序号不在窗口内, 当 discord 服务器收到这些报文时, 在协议栈部分会直接丢弃这些报文, 从而不会干扰后续正常的 TLS 握手报文处理.
上述方案可行的很重要前提就是运营商只会对连接建立后的极少量报文进行内容检测。这么做的原因也很合理, 因为深度报文检测(DPI)需要成本, 对前几个报文进行检测绝大多数情况下已经够用。
type4 类型报文的识别也是属于 DPI 的范畴, 并且监管识别的特征也各不相同。
同样以俄罗斯地区对 discord 的封锁为例, 除了上面提到的 https 登录流量外, 运营商还会识别并封锁 udp 语音通道. 识别方法是检测 UDP 流的前若干个报文的特征, 如果符合 discord 语音通道的特征, 就阻止该流量通过
下图是正常情况下的 udp 通道建立时的 payload 内容
zapret 采用的突破方法和 type3 类型类似, 也是在发送真实 udp 报文前, 先发送若干个 fake 报文, 与 TCP 不一样的是, UDP 没有序号的概念, 因此, 这里的伪造报文是 payload 全为 0 的报文.
监管者 DPI 审查这些报文通过后, 就不再拦截这个四元组的后续报文.
下图是填充了 6 个 fake 报文后的报文交互情况
当然这个方案能成立的条件是 discord 服务器能允许兼容收到 pyaload 全 0 的报文而不会中断连接。
回到 GFW。长期以来, 使用一些科学上网软件(如shadowsock)被认为是突破 GFW 的一种有效方然.
然而, 根据互联网上的一些资料, 2021年11月初,GFW 部署了一种新的技术,影响到一大批流行的科学上网协议。
根据研究者的实验结论, GFW 的封锁分为被动检测和主动探测两种,前者是指使用 DPI 方式审查全加密流量, 看其是否合法, 后者是指利用重放/修改重放等方式去主动探测境外服务器是否为代理服务器。
研究对GFW被动检测和封锁全加密流量的新系统进行了测量和描述, 结论是: 审查者没有直接定义什么是完全加密的流量,而是应用了至少五条粗糙但高效的启发式规则来豁免那些不太可能是完全加密的流量;然后,它阻止其余未豁免的流量
五条规则如下:
如果一个TCP连接的第一个数据包的有效载荷与上述任何规则相匹配,GFW就会豁免该连接。未被任何规则豁免的流量将被阻止.
每条规则的详细意义可参考原文
(a) popcount豁免(Ex1):GFW计算每个字节的平均1比特数(popcount),作为衡量熵的粗略标准,如果该值小于3.4或大于4.6,则豁免连接。
(b) 前六个字节为可打印的ASCII的豁免规则(Ex2): 如果一个连接的前六个(或更多)字节都是可打印的ASCII,则GFW将其豁免。
(c) 半数字节为可打印的ASCII的豁免规则(Ex3):如果一个连接的第一个有效载荷有超过50%的可打印的ASCII,则GFW将其豁免。
(d) 连续可打印豁免(Ex4):GFW计算连续可打印的ASCII字节的最大数量,如果该值超过20个字节,则豁免连接。
(e) 协议豁免(Ex5):如果一个连接的前几个字节符合HTTP或TLS协议,则GFW豁免其连接。
对于协议设计者的启示是, 1.需要对连接建立开始后的报文进行修改 2.不能让修改后的报文完全不像正常报文
参考资料
zapret: https://github.com/bol-van/zapret