首先,我们要知道 GFW 是如何封锁我们的流量的#
-
IP 黑洞:目前无解,但仅对部分服务黑洞,如谷歌系(谷歌、推特、YouTube 等)
-
DNS 污染:为域名返回一个假的 IP。使用 hosts 文件强制指定域名对应 ip 或者使用加密的 DNS(DoH、DNS 签名等)
-
HTTP 劫持:因为流量不是加密的,GFW 作为天然的中间人可以直接进行篡改(如:重定向到 404 页面、劫持到反诈页面等)。可以使用 HTTPS 连接规避,但你可能会遇到 SNI 阻断
-
SNI 阻断:在客户端与服务器建立加密连接前,客户端会发送
Client Hello
报文,而这个报文是明文,并且一般都会携带server_name
,GFW 可以知道你要访问哪个网站,对不在白名单(如:discord.com)的域名进行阻断。因为server_name
实际上是一个扩展,并不强制,你可以不发送它来规避 SNI 阻断
那么,让我们分析一下 GFW 对于不同网站的封锁情况#
我们使用 WireShark 进行抓包
-
首先尝试访问
www.baidu.com
这是一个没有被 GFW 封锁的域名-
我们先 ping 一下
-
得到 ip:
2408:873d:22:18ac:0:ff:b021:1393
-
通过 Hosts 强制绑定
-
通过 WireShark 进行抓包,可以看到,客户端发送的
Client Hello
可以清晰地看到Server Name
字段,并且也能正常收到Server Hello
然后双方便开始通信
-
查看浏览器,网站正常访问
-
-
让我们试试访问
discord.com
-
我们先 ping 一下,可以发现,域名和解析到的 IP 均不通
-
此时我们尝试使用
itdog.cn
进行 v4 ping,并且依次对解析出的域名进行 ping
-
可见,第一个 IP 通
-
强制绑定 Hosts,尝试抓包
-
- 可见,在通过强制 Hosts 绑定后,在客户端发送
Client Hello
后被 GFW 检测到Server Name
字段,然后 GFW 向客户端发送一个RST
报文,即要求重置客户端连接。在客户端侧,则会收到ERR_CONNECTION_RESET
即:连接已重置。用户无法访问网页。
继续,尝试发送空 Server Name
报文#
成功访问。在 WireShark 中并未发现 Server Name
字段
杀手锏,tcpioneer#
它通过魔改 TCP 数据包使得 GFW 无法检测,并且 WireShark 也无法抓取到Client Hello
报文,但是仍然能建立连接,即服务端发送Server Hello