2023年关于河南GFW的新模式科普以及应对方案

xiaohuangbo 1.6K 4
摘要:

重点是在于不要让你的客户端听信GFW伪造出来的“连接重置”的的“谗言”,在第一次客户端与服务端连接时就发现双方都支持timestamps时间截,之后发送的第二次连接中双方都会使用头部多出10字节的时间截,再之后第三次连接由GFW伪造出来的“重置连接”的包不带有timestamps时间截,客户端一眼识破GFW的“阴谋”,肯定不会照着把连接断开而是直接会把这连接重置的“假”包忽略掉,之后就与服务端顺利进行三次握手实现长连接继续上外网了。

引言

(本文首发于twitter.com,原作者就是我)

大家在河南的可能已经都知道了最近河南那边的GFW竟然更新了,经过不断摸索,总算是搞清楚是怎么回事以及应对方案了。

宇宙安全声明!本文仅仅是科普网络攻防安全技术!并不涉及其它敏感内容!!

本文已经过审查,本站域名更换的原因……你懂的嘛XD

首先GFW“黑名单”是什么?

GFWList,我将其称作“黑名单”。是通过一个存储GFW所墙网站列表的庞大项目。这个项目由网友齐心协力完成,涵盖了大多数普通用户需要访问的外网。用户发现了可能被封锁的网站,将会提交至项目,维护者通过审核,再三确认后将其载入名单。[1]

一切的开端,人们是如何绕过GFW的?

其实原因可能是因为大量的翻墙用户使用Trojan等协议进行“翻墙”,而Trojan协议的伪装方式是使用TLS加密流量来让GFW看上去像是在用HTTPS协议正常访问一个境外网站而已。 但这并不能一直都骗过GFW,当你的连接出现“时间长 高并发 大流量 多境内IP连接”的流量特征时,就会引发GFW的“主动探测”[2],还好Trojan协议允许你进行站点“伪装”(websocket),让正常访问网站的GFW看到的是一个英文网站之类的,也能骗过GFW认为你是在正常访问一个网站而不是用它翻墙,但就长期而言,这样的方式有风险,一旦GFW认为你是在利用这个站点搭代理“翻墙”,轻则把你连接的端口封掉(通常HTTPS走的是443端口),重则就会把整个IP和域名加入“黑名单”(也就是说所有经过GFW发往这个IP/网站的包,包括TCP/UDP都会被丢掉)

但这种方法毕竟封锁效率有限,有时还得人工识别,再加上现在有很多协议(v2ray xTLS等)都可以走CDN转发这些TLS流量[3],而CDN的IP又是一大堆,上面还有一些其它正常的网站走的也是这些IP,简单的封锁这些IP反而会“误伤”到这些正常的通往境外网站的流量(那就真成朝鲜了.jpg)。

反转:GFW的升级

正当大家以为可以长期挂代理高枕无忧时,这个河南GFW来了个升级很好的“解决”了这个“问题”,用方法就是经典的“RST复位攻击”![4](没错就是你以前早些年访问谷歌时看到的那个“连接已重置”),原理是当你用基于TCP连接的协议时(TLS就是基于TCP连接的协议),河南GFW就会在长连接建立的几分钟之后向你境内客户端这边伪造一个RST包,这时你的客户端就会毫无疑问的丢弃与服务端的缓冲区上所有数据,强制关掉连接。之后你的每一次都会像图那样直接被GFW伪造的RST包阻断。

F3UlU7hbYAE3Vzv

图①-GFW的RST攻击方式

据TG网友 @MiyamotoKonatsu 测试,这个攻击阀值很低,虽然说是黑名单,但是跟那次泉州模式似的连几分钟就给你发RST包阻断就他妈离谱!(虽然还是比泉州模式泉州模式好的是毕竟还是黑名单,陌生的境外网站不会默认给你来个阻断,而是长连接还会给你保持着几分钟后再给你发RST包阻断,它真的,我哭死QWQ)

F3UsKFMaQAAqozV

如此低的阈值让人惊讶

猫鼠游戏:惊讶的发现

所以……难道我们就真的无能为力了吗? 当然不是!俗话说得好,只要思想不滑坡,办法总比困难多v2ray core项目的开发者以及志愿者进行了讨论和研究[5],如果是服务端和客户端都支持Timestamps的话那么tcp每个包都会带有额外的10bytes timestamps时间截,那么在GFW重置连接的RST数据包时就会被直接丢掉,这将表现为没有影响

那么什么是tcp连接中Timestamps呢?

timestamps是作为一个 TCP 选项存在于 TCP 首部。引入 timestamp 最初有两个目的:1.更精确地估算报文往返时间(round-trip-time, RTT) 2. 防止陈旧的报文干扰正常的连接.[6]TCP Timestamp 选项虽然能带来好处, 但并不是所有的 TCP 连接都会使用该选项,比如 Windows 系统就是默认不不启用该选项的,而 Linux 系统则是默认启用了该选项。 据 tcpm 的统计,在全球范围内,使用了 TCP Timestamp 的连接比例大概为 60%~70% 。[7]

不支持 TCP Timestamp 的理由是该选项占用的报文长度太多了,它会占用 TCP 报文首部的 10 个字节,而且是每个报文都会有这种损耗。 好巧不巧,据v2ray core开发者测试,所有由GFW发送的RST包都是没有Timestamp的!那就是说如果代理服务端和客户端都使用带有Timestamp的tcp连接的话那么由GFW发送的不带有Timestamp的RST包就会被忽略!那么连接就会顺利进行下去了!我们就又能够愉快的与代理服务器握手连接了!♪(^∇^*)

(显然人们不知道自己的设备有没有开 TSopt,有的默认开了就没被阻断,这就是人们对河南新上的 SNI 黑名单说法不一的原因之一)

据telegram用户的小道消息传言,明年的四月这阴间阻断将在全国实施

F3UlFQ3aUAE MI8

TG群的小道消息

所以我现在呼吁各位翻墙用户都把自己客户端/服务端的timestamp选项打开!

转折:如何打开tcp连接中的timestamp选项?

在你的服务端和客户端都必须启用你的timestamp选项,tcp连接才会在之后的头部带上timestamp!

如果你是linux作为服务端/客户端,那么恭喜,你的timestamp选项应该是默认开启的,不过我还是建议您在控制台中输入以下指令把这个选项再确认开启一下(ipv6也会生效):

sysctl -w net.ipv4.tcp_timestamps=1

如果您是windows用户或者使用winsever来做的代理服务器,那请您使用管理员权限打开powershell,然后输入以下指令:

netsh interface tcp set global timestamps=enabled

如果你是安卓用户,那么不是国产流氓魔改系统的话请将您的系统升级为最新版本(安卓10以上)

如果您有root权限,您可以通过以下步骤尝试更改TCP timestamp选项:

1. 使用Root权限的文件管理器:

- 在您的Root设备上安装一个能够访问系统文件的Root文件管理器应用,例如"Root Explorer""ES File Explorer"(请确保下载安全的应用)或"MT管理器"。

- 找到并编辑系统配置文件 `/proc/sys/net/ipv4/tcp_timestamps`。

2. 使用终端模拟器应用:

- 安装终端模拟器应用,例如"Termux"。

- 打开终端模拟器并获取Root权限:`su` - 使用命令来更改TCP timestamp选项:`echo 0 > /proc/sys/net/ipv4/tcp_timestamps`

(0表示禁用,1表示启用)

完成!

这样你的客户端/服务端就支持timestamps了!下次连接时的tcp首部都将带有timestamps时间截!

(目前已知的情报:

墙不给 开了TCP Timestamps的固定宽带网络 发RST, 给没开TCP Timestamps选项的固定宽带网络发RST,。

对于数据流量网络,无论开不开TCP Timestamps,墙都会发伪造的RST。 无论任何一种情况,均未收到过带Timestamps的 RST。

这个离谱的技术其实上是某些公司研发出来的产物,被河南那边的“小天才”发现拿去直接套用在了GFW上。)

F3V18qlaQAAjBQB

总结

重点是在于不要让你的客户端听信GFW伪造出来的“连接重置”的的“谗言”,在第一次客户端与服务端连接时就发现双方都支持timestamps时间截,之后发送的第二次连接中双方都会使用头部多出10字节的时间截,再之后第三次连接由GFW伪造出来的“重置连接”的包不带有timestamps时间截,客户端一眼识破GFW的“阴谋”,肯定不会照着把连接断开而是直接会把这连接重置的“假”包忽略掉,之后就与服务端顺利进行三次握手实现长连接继续上外网了。[斜眼笑][调皮]

展望未来/后记

开启时间戳是利用PAWS机制来丢弃时间戳和seq不同步的TCP报文,如果 GFW 给 RST packet 加上 timestamp,那么该方案即失效

理论上是伪造的RST包有可能带有正确的timestamps的,但技术上我还不知道GFW那边能不能实现,但那些都是后话了(◔◡◔)

也许将长连接变为(多个)短连接是更好的方案。多路复用(multiplex)就是 method 之一。

如今,sing-box 有多种 mux 方案,Xray 也宣布了新的 switch 流控。多路复用从根本上会消除「长连接」特征。

GFW的工作原理是未知的。而科学上网是已知,都是开源的。这是一个不对等的游戏。对抗封锁方处于劣势中,一群不为金钱冒着被捉的风险。这些人都是英雄。

──来自推特网友

[1]https://medium.com/@hackl0us/%E4%B8%80%E9%BB%91%E4%B8%80%E7%99%BD-2%E5%A5%97%E8%A7%84%E5%88%99%E8%B6%B3%E7%9F%A3-e008cbc87570

[2]https://chinadigitaltimes.net/chinese/342752.html?amp

[3]https://v2xtls.org/v2ray%E4%BD%BF%E7%94%A8cloudflare%E4%B8%AD%E8%BD%AC%E6%B5%81%E9%87%8F%EF%BC%8C%E6%8B%AF%E6%95%91%E8%A2%AB%E5%A2%99ip/

[4]https://www.51cto.com/article/631439.html

[5]https://github.com/XTLS/Xray-core/issues/2426

[6]https://switch-router.gitee.io/blog/tcp-timestamp/

[7]https://mailarchive.ietf.org/arch/msg/tcpm/861z901kDYtHSWxDOsic_Ejpqz8/

发表评论 取消回复
表情 图片 链接 代码

  1. Bin
    Bin Lv 1

    color OS是开不了吗,看了一下timestamps文件,内容是2
    ……

    • xiaohuangbo
      xiaohuangbo 站长

      @Bin这个已经在v2ex讨论出新的方法了,https://www.v2ex.com/t/970368?p=2 目前可以通过直接暴力丢弃所有的RST包解决,但是这种无脑丢弃RST包的方式可能会导致不可预料的网络问题。
      <code>
      #服务器端和本地端都运行,丢弃RST包
      iptables -I INPUT -p tcp --tcp-flags RST RST -j DROP
      #网关用这个可以丢弃转发的数据包中的RST包,使得网关下的设备都能恢复访问
      iptables -I FORWARD -p tcp -i pppoe-wan --tcp-flags RST RST -j DROP
      #pppoe-wan换成你的出口接口
      </code>

  2. 3948
    3948 Lv 1

    我想问一下,假如未来GFW会发送带有伪造的timestamp的rst包的话,这个方法就会失效。届时,可不可以干脆就不管timestamp,而是直接一刀切在客户端上丢弃所有收到的rst包来避免被阻断?一刀切丢弃全部收到的rst包(考虑到rst包在正常情况下也具有紧急中断tcp连接的作用)是否会导致其他的潜在风险?
    另外河南那边是如何判断该给那条连接发送rst来阻断呢?是对单一境外IP的长连接(也就是被怀疑可能为加密代理的可疑流量)吗?我看到网上的一些反馈说在河南访问正常境外网站也被阻断,疑似和域名有关,其中.xyz的域名阻断频率非常高,无论是搭建代理还是正常网站都会触发阻断。

    • xiaohuangbo
      xiaohuangbo 站长

      @3948您好,未来GFW带timestamp的rst包是有可能的,当然用你的方法直接在路由器或者软件层面上忽略掉所有RST包其实也不是不可以,但会导致一些进程出现“占着茅坑不拉屎”的情况,浪费资源,有些进程甚至还得手动杀死,所以不推荐这样的做法。至于判定原理,之前发现只要通向境外所有非白名单服务器的连接(在GFW白名单之外的境外服务器)超过几分钟GFW就会发送RST包阻断,但目前为止没有发现RST包带timestamp。河南福建GFW阻断率还是非常高的。至于是否针对.xyz的域名我也不是很了解,因为GFW闭源,每个地区的GFW策略都不一样,所以还需要证据来待证明

分享