Skip to content

Latest commit

 

History

History
388 lines (232 loc) · 51.5 KB

dive-into-gfw.md

File metadata and controls

388 lines (232 loc) · 51.5 KB

深入理解 GFW:内部结构

更新:本文中的图像链接因为Google Docs改版失效已修复。Update: fixed some broken image links included here.

之前我们对GFW进行了大量的黑箱测试,尽管大多数实验数据都得到了良好的解释,但是还是有些数据或者体现出的规律性(不规律性)没有得到合理的解释。比如TCP连接的各项超时时间,比如Google的443端口被无状态阻断时,继发状态的持续跟源IP相关的问题。比如一般TCP连接的继发阻断时,窗口尺寸和TTL的连续变化特性。这些问题已经超出纯协议的范畴,需要对GFW的内部结构进行进一步了解才能明白其原因。所以在这一章介绍GFW的实现和内部结构。
总的来说,GFW是一个建立在高性能计算集群上规模庞大的分布式入侵检测系统。其分布式架构带来了很高的可伸缩性,对骨干网一点上庞大流量的处理问题被成功转换成购买超级计算机堆砌处理能力的问题。它目前有能力对中国大陆全部国际网络流量进行复杂和深度的检测,而且处理能力“还有很大潜力”(2009年8月)[null]

线路接入

典型意义下GFW线路拓扑

svg

对于GFW在网络上的位置,有很模糊的认知:“在三个国际出口作旁路监听”。然而还希望对在出国之前最后一跳之前发生了什么有详细了解。
GFW希望对不同线路的链路异构性进行耦合,并研究了快速以太网、低速WAN、光纤、专用信号多种类型链路的耦合技术。[03b]而根据《国际通信出入口局管理办法》,几大ISP有自己的国际出入口局,最后在公用国际光缆处汇合,比如在海缆登陆站之前汇合。据已有的资料,安管中心(CNNISC)有独立的交换中心,而且有报道说各个ISP是分别接入其交换中心。这样几个材料就可以形成一致的解释:为了适应不同ISP不同的链路规格,GFW自己的交换中心需要对不同的链路进行整合,不同的ISP分别引出旁路接入GFW。而没有接入GFW的线路则被称为“防外线”[来源不可靠],不受GFW影响。接入的线路类型应该主要是光纤线路,因此通常称此接入方式为分光。这就是“旁路分光”。另外实验发现,GFW的接入地点并不一定紧靠最后一跳,因此图中以虚线表示。需要注意GFW的响应流量重新接回网络的地点难以确认,这里只是假设是与接出的地点相同。

负载平衡

面对多条骨干监测线路接入产生的巨大不均匀流量,不能直接接到处理集群,而是要先进行汇聚然后再负载均衡分流成均匀的小流量,分别送给处理集群并行处理。首先需要将网络设备通信接口(Pos、ATM、E1等)转换成节点可用的主机通信接口(FE、GE等)。处理负载均衡的算法经过仔细考虑,希望实现:流量均匀分布、对于有连接协议保持连接约束、算法简单。连接约束是指:一对地址端口对之间的一个连接全部通信都要保证调度到同一个节点。[03b][03a][05a]
GFW关于负载平衡的文章中主要提出两种算法。一种是轮转调度,对于TCP,当SYN到达时,以最近分配的节点号取模再加1,并将连接存入hash表,当后继流量到达时就能查询hash表获得目标节点号。[03a]另一种是基于连接参数的散列,对于N个输出端口调度输出端口号是H(源地址, 目标地址, 源端口, 目标端口) mod N[03b],这个H函数可以是xor[05a]
而之前的某个实验中我们碰到一种特殊的模式,负载平衡在解释其现象中起到了重要作用,下面专门分出一节详细说明。

一个关于窗口值的实验

实验步骤:发送含有关键词的特制包通过GFW,并接收GFW返回的阻断响应包。因为触发阻断之后,同地址对和同目标端口的连接都会受到继发阻断,为了消除这种干扰,一般采取顺序改变目标端口的扫描式方法。通过前期一些实验,我们已经发现和确认某类(二型)阻断响应包中的TTL和id都跟窗口大小有线性关系,我们认为窗口是基本量(二型窗口为5042时id发生了溢出,只有在id根据窗口算出时才会发生此种情况)。
然而在顺序扫描中有一种特殊的模式无法用现有证据解释。进一步的实验步骤是:在源、目标地址不变的情况下,顺序扫描目标端口,记录返回的阻断响应包的窗口。数据如下图,横轴是时间(秒),纵轴是端口号,每个点代表一次阻断触发事件中观测者收到的阻断包的窗口值。

可以明显看出一种线性增加的趋势。图像取局部放大看:

可以看出,在同一时间有13根较连续的线。这样产生了几个问题:为什么有独立可区分的不同的线?这些线表示了什么?为什么有13根?为什么每根线是递增的?

  • 为什么有独立可区分的不同的线?现象具有明显的可以继续划分的子模式,而不是一个整体的随机量,并且每个子模式都有良好的连续增加的性质。因此可以推测产生此现象的内在机制不是一块铁板,而是多个独立的实体。进一步的实验事实是,如果顺序扫描端口每次增加13,那么只会产生一条较连续的线而排除其他的线。这直接证明了模13同余端口产生结果的不可分性、实体性,以及同余类间的独立性。
  • 这些线表示了什么?我们猜想,这13根线就表征了背后有13个独立实体分别根据某个内在的状态产生阻断响应,窗口值就是其内在状态的直接表现。
  • 为什么有13个?而不是1个2个?这个时候,负载平衡就是对此事实的一种解释良好的模型。如果GFW有13个节点在线,由于希望将流量平均分配到每个节点,那么根据前面论文所述,便采用模的方式,在源、目标地址不变时,根据目标端口模13分配流量,目标端口模13同余的包会进入同一个节点。实际上更早的时候的一次实验是发现有15根线,同理可以猜测有15个节点在线。
  • 为什么每根线是递增的?实验中发现,每次阻断GFW会分别向连接双方发送窗口值依次增加的两组阻断包,这样对于每方来说,每次阻断就会使窗口值增加2。每根线会递增正是说明节点在不断产生阻断包增加窗口值,一部分是实验观察者的观测行为触发的,另一部分则是普通网络流量造成的。如果对数据做差分并扣除观测造成的影响,甚至还可以对每节点产生阻断的速率有所估计。
  • 但是为什么要让窗口递增?这背后的动机难以找到很合理的解释,可能这个窗口值有计数器的作用,也可能是为了在ip.id上对不同节点产生的包进行区分。事实上,一型的窗口值就是几乎随机但ip.id固定,窗口递增并非是必须的。

然而进一步的实验发现,如果目标端口、源地址不变,而目标地址顺序变化,图像就显得比较紊乱,找不出规律。虽然如此,仍然在局部可以识别出同时存在13根线的情况,进一步证实“13个节点在线”的猜测。这个实验的意义在于,通过对现象的分解约化,分离出GFW内部的某种独立实体结构,对论文中主张的负载平衡算法有进一步的实践证实,对GFW的内部结构得到进一步的认识。[*]

数据处理

当数据流通过当数据总线到达终端节点之后,需要将其从物理层提取出来供上层进一步分析,这个部分称为报文捕获。普通的做法,先网卡中断一次通知内核来取,然后控制DMA传到内核空间,然后用户用read(),让内核copy_to_user()将sk_buff的数据复制到用户空间,但是这样复制一次就带来了无谓开销。因此GFW设计环状队列缓存,以半轮询半中断机制减少频繁中断的系统调用开销,用mmap实现zero-copy,把数据直接从网卡DMA到用户空间。这样性能提高很多(耦合也提高很多)。[**]
链路层数据到怀里了,接下来要将数据上交给TCP/IP栈。论文中多次提到libnids(这个库我们也是第一眼就瞟到了,后来发现对诊断没什么用),将其作为基准,(甚至可能符合国情地)以其为蓝本改进,开发出了一种多线程的TCP/IP(自动机)。后面又在考虑对其进一步做自动机分解优化。后来又再次提出一种两级连接状态记录表,一级轻量级环状hash表可以缓解大量无效连接和SYN Flood的情况,二级表才真正存储连接的信息。实验结果与此相符:发送SYN之后的超时时间要比发送第一个ACK之后的超时时间短得多。文献中还提到libnids的half_stream,从实际的情况上看,GFW的TCP栈的确具有鲜明的半连接特性,也就是说:一个方向的TCP栈只检测客户端到服务端的数据,或者反之。这样一个直接的后果就是,即使服务端根本不在线没响应,客户端照样可以假装三次握手然后触发一堆RST。往好的方向看,也许是因为多线程TCP栈还原全连接时不想处理数据共享控制的问题。总而言之,GFW有一种非常轻量级的TCP/IP栈,刚好能够处理大多数遵守RFC的连接。如果用户稍微精明一点就能穿过去,GFW要么坐视不管,要么重写TCP栈。[***]
TCP/IP栈将数据分片重组,流重组之后交给应用层解析。应用层由很多插件模块组成,耦合松,部署易。其应用层插件包括“HTTP、TELNET、FTP、SMTP、POP3、FREENET、IMAP、FREEGATE、TRIBOY”。[05a]有意思的是,这是首次官方确认GFW与Freegate、Freenet、Triboy的敌对关系。应用层的协议大家都很熟悉不用多解释,不过应用层问题比传输层更多了。好几个模块都有一些小毛病,比如某类HTTP模块只认得CRLF作为EOL,换作LF便呆了。再比如某类DNS模块,发的DNS干扰包,十有五六都校验和错误,查询AAAA也返回A,还不如关掉。多数模块都是得过且过,刚好可以工作,一点都不完善。这里列出的、发现的问题按照软件设计一般规律也只是冰山一角。由此推断,GFW的设计哲学是:better is worse。
不过在可以生产论文的话题上,GFW绝不含糊,就是模式匹配。应用层模块把应用层协议解析好了,然后就要看是不是哪里有关键词,字符串匹配。搞了一堆论文出来,改进AC算法和BM算法,就差汇编的干活了,得出某种基于有限状态自动机的多模式匹配算法,特别适合GFW这种预定义关键词的需求。总之复杂度是线性的,攻击匹配算法消耗CPU什么的就不要想了。

响应机制

如果匹配到一个关键词了,要积极响应阻断之。响应的手段其他地方已经说得太多,手懒,特此剽窃一段,欢迎举报学术不正之风:

响应机制的发展已经经历IP包过滤(静态IP包过滤、动态IP包过滤)、连接欺骗(传输层连接欺骗、应用层连接欺骗)两个阶段,并且形成了针对不同的应用多种方式共存的现状。
静态IP包过滤是IDS通过和被保护网络与外部网络之间的连通边的端点网络层设备(路由器、三层交换机等)进行联动,在其上设置访问控制列表(ACL)或静态路由表来实现对指定IP地址的过滤。由于需要过滤的IP地址数量很大,大多数的网络层设备上对ACL大小和性能的支持不能满足要求,因此,实际工作中大多采用静态路由的方式。使用该种方式,信息入侵检测系统只能通过专用客户端程序静态写入的方式进行访问控制,粒度大(IP地址级),响应时间慢,容量较小,但是可以静态写入路由设备的配置文件中,是非易失的。
动态IP包过滤是指入侵检测系统采用动态路由协议(BGP,OSPF等)和关键路由设备进行路由扩散,将需要过滤的IP地址扩散到路由设备中的路由表中,特点是响应时间快、容量大,但是只能动态地写入路由设备内存(RAM)中的路由表中,是易失的,同样粒度大。
连接欺骗指信息入侵检测系统在敏感连接传输过程中伪造连接结束信令(RST,FIN)发送给连接的源和目的地址,以中断该连接。特点是实时性强、粒度小(连接级),可以针对某一次敏感连接进行阻断。缺点是对分析系统工作状态依赖较强,需要向业务网上发送数据包,易受DoS攻击。
通过和连接级防火墙设备进行联动,可以针对连接五元组(传输协议类型、源地址、源端口、目的地址、目的端口)对数据流进行过滤。可以针对指定的任意五元以内的组合条件进行过滤,实时性强、粒度小。

后来又加上了DNS劫持/污染,不过这个手动设置的机制已经不能算一个入侵检测系统的响应了。

日志记录

GFW有日志。这意味着什么?这就意味着当你芬兰国的时候,你的所作所为都记录在案。不光是你一个人,其他所有人都经常芬兰国。但据统计87.53%的人(361之316)都是无意之中芬兰国,从统计理论上看,记录在案的无效信息过多会造成信息难以利用。因此GFW后期一直在做“数据融合、聚类、分类的研究”,鸭子硬上弓,各种神经网络、概率模型、人工智能的论文整了一大堆,效果如何呢?
GFW的日志应该会记录这样一些事件信息:起始时间、结束时间、源地址、目标地址、目标端口、服务类型、敏感类型。[null]信息难以利用不等于不能利用,如果日志被翻出来了而且用户没有用代理,那么根据常识,从IP地址对应到人也只是时间问题。这就是说,GFW即使不能阻断,最差也是一个巨型监听设备。

规模估计

问题:

GFW的软硬件配置?

事实:

“虚拟计算环境实验床”是由国家计算机网络应急技术处理协调中心(CNCERT/CC)和哈尔滨工业大学(HIT)协作建设,以国家计算机网络应急技术处理协调中心遍布全国31个省份的网络基础设施及计算资源为基础,对分布自治资源进行集成和综合利用,构建起的一个开放、安全、动态、可控的大规模虚拟计算环境实验平台,研究并验证虚拟计算环境聚合与协同机理。2005年此平台配置如下:[05b]

CNCERT/CC

北京

曙光4000L

128节点

2*Xeon 2.4G

RAM2G

HIT

哈尔滨

曙光服务器

32节点

2*Xeon 2.4G

RAM2G

CNCERT/CC

上海

Beowulf集群

64节点

2*AMD Athlon 1.5G

RAM2G

结论:

GFW(北京)使用曙光4000L机群,操作系统Red Hat系列(从7.2[03a]到7.3[05a]到AS 4),周边软件见曙光4000L一般配置;GFW实验室(哈工大)使用曙光服务器[05b],Red Hat系列;GFW(上海)使用Beowulf集群(攒的?)。

问题:

GFW与曙光是什么关系?

事实:

换句话说,是先有了用户的应用需求(蛋),才有了曙光4000L的研制(鸡)。这其实不难想像,一套价值几千万元的系统,如果纯是为了填补科学空白,将会延长产品市场化的时间。曙光4000L充分体现了中科院计算所在科研成果市场化方面的运作能力。……而曙光4000L这套系统就是针对国家信息化的实际应用而设计的。 曙光4000L的研制……曙光公司从事了工程任务和产品化工作,国防科技大学从事了机群数据库中间件的开发工作,哈尔滨工业大学开发了应用软件。 哈尔滨工业大学(威海)网络与信息安全技术研究中心日前成立,……方滨兴……揭牌。……曙光……向研究中心赠送了一套价值40万元的刀片服务器。

结论:

GFW是曙光4000L的主要需求来源、研究发起者、客户、股东、共同开发者。是不是应该打一点折?(曙光公司=中科院计算所)

问题:

GFW计算规模有多大?

事实:

2007年机群规模进一步扩大,北京增至360节点,上海增至128节点,哈尔滨增至64节点,共计552节点。机群间星型千兆互联。[null]计划节点数上千。[null] 曙光4000L……系统节点数为322节点,可扩展到640节点。根据功能的不同,曙光4000L可以分为服务节点、计算节点和数据库节点三类。每个计算节点2个2.4GHZ的Intel Xeon CPU,内存2GB。 2005年国家计算机网络与信息安全管理中心(北京)就已经建立了一套384*16节点的集群用于网络内容过滤(005工程)和短信过滤(016工程)。[来源不可靠] 64个节点、128个处理器(主频为2.8GHz)的曙光4000L……包括系统软件、管理软件、输入输出设备和存储设备,采购金额近千万。 才有了曙光4000L的研制……一套价值几千万元的系统。 国家信息安全重大项目“国家信息安全管理系统”(005工程)经费4.9亿。

猜测:

GFW(北京)拥有16套曙光4000L,每套384节点,其中24个服务和数据库节点,360个计算节点。每套价格约两千万到三千万,占005工程经费的主要部分。有3套(将)用于虚拟计算环境实验床,计千余节点。13套用于骨干网络过滤。总计6144节点,12288CPU,12288GB内存,峰值计算速度48万亿次(定义不明,GFW不做浮点运算,2003年top500排名榜首地球模拟器5120个CPU)。

问题:

GFW吞吐量有多大?

事实:

2GHz CPU的主机Linux操作系统下可达到600Kpps以上的捕包率。通过骨干网实验,配置16个数据流总线即可以线速处理八路OC48接口网络数据。[03b] 曙光4000L单结点的接入能力为每秒65万数据包,整个系统能够满足32Gbp的实时数据流的并发接入要求。

猜测:

512Gbps(北京)。

结论

噫吁嚱!危乎高哉!……

注释

  • null引用有特殊含义。
  • [*] 因为性能要求,负载平衡的完整算法必然很简单,不过我们一下子也没有猜出来。由于这个算法是易变的,即使猜出来公布在这里就立刻失效了,因此也没有在这个方向再费精力。
  • [**] 顺便指出论文中存在的一种硬伤。论文中反复把libpcap当反面教材作为性能低下的代表,称其是“传统TCP/IP栈之上的用户层函数库”“基于传统TCP/IP栈的libpcap”。可是人家libpcap从2001年1月的0.6版本就开始用2.2以上版本内核提供的packet(7) socket,这个跟TCP/IP一点关系都没有。怪罪的对象错了,要怪的是packet(7)而不是libpcap。后来2004年PF_RING出来,设计很相似,libpcap用上一样nb。不过这个时候GFW也已经研发完了。
  • [***] 如果将其视为bug而不是feature的话,漏洞实在太多,打一两个补丁不解决问题,非重做不可。另外IP碎片和TCP流重组没有做特别研究,即使有漏洞实用性也不会很高。
  • [03a] 杨武, 方滨兴, 云晓春, 张宏莉. 基于骨干网的并行集群入侵检测系统. 哈尔滨工业大学学报. 2003-5-15.
  • [03b] 陈训逊, 方滨兴, 李蕾. 高速网络环境下入侵检测系统结构研究. 计算机研究与发展. 2003-7-15.
  • [05a] 张兆心, 方滨兴, 胡铭曾. 支持IDS的高速网络信息获取体系结构. 北京邮电大学学报. 2005-2-25.
  • [05b] 张伟哲, 方滨兴, 胡铭曾, 刘欣然, 张宏莉, 高雷. 计算网格环境下基于多址协同的作业级任务调度算法. 中国科学 E辑:信息科学. 2005-12-25.
  • 猜测之数字准确性无担保,请自行把握。

深入理解 GFW:DNS污染

初识DNS污染

翻墙新手们往往遇到这样的问题:我明明已经设置了socks代理为127.0.0.1:xxxx,为什么还是上不去youtube?这时经验丰富的翻墙高手就会告诉你:firefox需要设置network.proxy.socks_remote_dns为true,也就是远程解析域名。这是怎样一回事呢?为什么要远程解析?这就涉及到了GFW的DNS污染技术。

DNS(Domain Name System)污染是GFW的一种让一般用户由于得到虚假目标主机IP而不能与其通信的方法,是一种DNS缓存投毒攻击DNS cache poisoning)。其工作方式是:对经过GFW的在UDP端口53上的DNS查询进行入侵检测,一经发现与关键词相匹配的请求则立即伪装成目标域名的解析服务器(NS,Name Server)给查询者返回虚假结果。由于通常的DNS查询没有任何认证机制,而且DNS查询通常基于的UDP是无连接不可靠的协议,查询者只能接受最先到达的格式正确结果,并丢弃之后的结果。对于不了解相关知识的网民来说也就是,由于系统默认使用的ISP提供的NS查询国外的权威服务器时被劫持,其缓存受到污染,因而默认情况下查询ISP的服务器就会获得虚假IP;而用户直接查询境外NS(比如OpenDNS)又可能被GFW劫持,从而在没有防范机制的情况下仍然不能获得正确IP。然而对这种攻击有着十分简单有效的应对方法:修改Hosts文件。但是Hosts文件的条目一般不能使用通配符(例如*.blogspot.com),而GFW的DNS污染对域名匹配进行的是部分匹配不是精确匹配,因此Hosts文件也有一定的局限性,网民试图访问这类域名仍会遇到很大麻烦。

观测DNS污染

“知己知彼,百战不殆”。这一节我们需要用到前面提到的报文监听工具,以及参考其DNS劫持诊断一节。在Wireshark的filter一栏输入udp.port eq 53可以方便地过滤掉其他无关报文。为了进一步减少干扰,我们选择一个并没有提供域名解析服务的国外IP作为目标域名解析服务器,例如129.42.17.103。运行命令nslookup -type=A www.youtube.com 129.42.17.103。如果有回答,只能说明这是GFW的伪造回答,也就是我们要观测和研究的对象。

伪包特征

经过一番紧密的查询,我们可以发现GFW返回的IP取自如下列表:

4.36.66.178 203.161.230.171 211.94.66.147 202.181.7.85 202.106.1.2 209.145.54.50 216.234.179.13 64.33.88.161

关于这八个特殊IP,鼓励读者对这样两个问题进行探究:1、为什么是特定的IP而不是随机IP,固定IP和随机IP各自有什么坏处;2、为什么就是这8个IP不是别的IP,这8个IP为什么倒了GFW的霉?关于搜索这类信息,除了www.google.com之外,www.bing.com有专门的搜索IP对应网站的功能,使用方法是输入ip:IP地址搜索。www.robtex.com则是一个专门收集域名解析信息的网站。欢迎读者留下自己的想法和发现:lol:。

从Wireshark收集到的结果分析(实际上更好的办法是,将结果保存为pcap文件,或者直接使用tcpdump,由tcpdump显示成文本再自行提取数据得到统计),我们将GFW发送的DNS污染包在IP头部的指纹特征分为两类:

  • 一型:

  • ip_id == ____(是一个固定的数,具体数值的查找留作习题)。

  • 没有设置“不分片”选项。

  • 没有设置服务类型。

  • 对同一对源IP、目标IP,GFW返回的污染IP在上述8个中按照给出的顺序循环。与源端口无关、与源IP目标IP对相关。

  • TTL返回值比较固定。TTL为IP头部的“Time to Live”值,每经过一层路由器这个值会减1,TTL为1的IP包路由器将不再转发,多数路由器会返回源IP一条“ICMP time to live exceed in transit”消息。

  • 二型:

  • 每个包重复发送3次。

  • 没有设置“不分片”选项。

  • 设置了“保障高流量”服务类型。

  • (ip_id + ? * 13 + 1) % 65536 == 0,其中?为一个有趣的未知数。ip_id在同一个源IP、目标IP对的连续查询之间以13为单位递减、观测到的ip_id的最小值和最大值分别为65525(即-11,溢出了!)和65535。

  • 对同一对源IP、目标IP,GFW返回的污染IP在上述8个中按照给出的顺序循环。与源端口无关、与源IP目标IP对相关。

  • 对同一对源IP、目标IP,TTL返回值时序以1为单位递增。TTL在GFW发送时的取值有64种。注:源IP接收到的包的TTL被路由修改过,所以用户观测到的TTL不一定只有64种取值,这是由于网络拓扑变化的原因导致的。一型中的“比较固定”的“比较”二字也是考虑到网络拓扑偶尔的变化而添加的,也许可以认为GFW发送时的初始值是恒定的。

(以上结果仅保证真实性,不保证时效性,GFW的特征随时有可能改变,尤其是时序特征与传输层特征相关性方面。最近半年GFW的特征在很多方面的变化越来越频繁,在将来介绍TCP阻断时我们会提到。)

还可以进行的实验有:由于当前二型的TTL变化范围是IP个数的整数倍,通过控制DNS查询的TTL使得恰好有GFW的返回(避免动态路由造成的接收者观察到的TTL不规律变化),观察IP和TTL除以8的余数是否有对应关系,在更改源IP、目标IP对之后这个关系是否仍然成立。这关系到的GFW负载平衡算法及响应计数器(hit counter)的独立性和一致性。事实上对GFW进行穷举给出所有关于GFW的结果也缺乏意义,这里只是提出这样的研究方法,如果读者感兴趣可以继续探究。

每次查询通常会得到一个一型包和三个完全相同的二型包。更换查询命令中type=Atype=MX或者type=AAAA或者其它类型,可以看到nslookup提示收到了损坏的回复包。这是因为GFW的DNS污染模块做得十分粗制滥造。GFW伪造的DNS应答的ANSWER部分通常只有一个RR组成(即一条记录),这个记录的RDATA部分为那8个污染IP之一。对于二型,RR记录的TYPE值是从用户查询之中直接复制的。于是用户就收到了如此奇特的损坏包。DNS响应包的UDP荷载内容特征:

  • 一型

  • DNS应答包的ANSWER部分的RR记录中的域名部分由0xc00c指代被查询域名。

  • RR记录中的TTL设置为5分钟。

  • 无论用户查询的TYPE是什么,应答包的TYPE总是设置为A(IPv4地址的意思)、CLASS总是设置为IN。

  • 二型

  • DNS应答包的ANSWER部分的RR记录中的域名部分是被查询域名的全文。

  • RR记录中的TTL设置为1天。

  • RR记录中的TYPE和CLASS值是从源IP发送的查询复制的。

其中的术语解释:RR = Resource Record:dns数据包中的一条记录;RDATA = Resource Data:一条记录的数据部分;TYPE:查询的类型,有A、AAAA、MX、NS等;CLASS:一般为IN[ternet]。

触发条件

实际上DNS还有TCP协议部分,实验发现,GFW还没有对TCP协议上的DNS查询进行劫持和污染。匹配规则方面,GFW进行的是子串匹配而不是精确匹配,并且GFW实际上是先将域名转换为字符串进行匹配的。这一点值得特殊说明的原因是,DNS中域名是这样表示的:一个整数n1代表以“.”作分割最前面的部分的长度,之后n1个字母,之后又是一个数字,若干字母,直到某次的数字为0结束。例如www.youtube.com则是"\x03www\x07youtube\x03com\x00"。因此,事实上就可以观察到,对www.youtube.coma的查询也被劫持了。

现状分析

  • 4.36.66.178,关键词。whois:Level 3 Communications, Inc. 位于Broomfield, CO, U.S.
  • 203.161.230.171,关键词。whois:POWERBASE-HK位于Hong Kong, HK.
  • 211.94.66.147,whois:China United Network Communications Corporation Limited位于Beijing, P.R. China.
  • 202.181.7.85,关键词。whois:First Link Internet Services Pty Ltd.位于North Rocks, AU.
  • 202.106.1.2,whois:China Unicom Beijing province network位于Beijing, CN.
  • 209.145.54.50,反向解析为dns1.gapp.gov.cn,新闻出版总署的域名解析服务器?目前dns1.gapp.gov.cn现在是219.141.187.13在bjtelecom。whois:World Internet Services位于San Marcos, CA, US.
  • 216.234.179.13,关键词。反向解析为IP-216-234-179-13.tera-byte.com。whois:Tera-byte Dot Com Inc.位于Edmonton, AB, CA.
  • 64.33.88.161,反向解析为tonycastro.org.ez-site.net, tonycastro.com, tonycastro.net, thepetclubfl.net。whois:OLM,LLC位于Lisle, IL, U.S.

可见上面的IP大多数并不是中国的。如果有网站架设到了这个IP上,全中国的Twitter、Facebook请求都会被定向到这里——好在GFW还有HTTP URL关键词的TCP阻断——HTTPS的请求才构成对目标IP的实际压力,相当于中国网民对这个IP发起DDoS攻击,不知道受害网站、ISP是否有索赔的打算?

我们尝试用bing.com的ip反向搜索功能搜索上面那些DNS污染专用IP,发现了一些有趣的域名。显然,这些域名都是DNS污染的受害域名。

DNS劫持的防范和利用

之前我们已经谈到,GFW是一套入侵检测系统,仅对流量进行监控,暂没有能力切断网络传输,其“阻断”也只是利用网络协议容易被会话劫持Session hijacking)的弱点来进行的。使用无连接UDP的DNS查询只是被GFW抢答了,真正的答案就跟在后面。于是应对GFW这种攻击很自然的想法就是:

根据时序特性判断真伪,忽略过早的回复。

通常情况对于分别处于GFW两端的IP,其RTT(Round-trip time,往返延迟)要大于源IP到GFW的RTT,可以设法统计出这两个RTT的合适的均值作为判断真伪的标准。另外由于GFW对基于TCP的DNS请求没有作处理,于是可以指定使用TCP而不是UDP解析域名。也可以通过没有部署GFW的线路没有被DNS污染的NS进行查询,例如文章一开始提到的“远程解析”。但黑体字标出的两个条件缺一不可,例如网上广为流传的OpenDNS可以反DNS劫持的说法是以讹传讹,因为到OpenDNS服务器的线路上是经由GFW的。

本质的解决办法是给DNS协议增加验证机制,例如DNSSEC(Domain Name System Security Extensions),客户端进行递归查询(Recursive Query)而不查询已经被污染了的递归解析服务器(Recursive/caching name server)。然而缺点是目前并非所有的权威域名解析服务器(Authoritative name server)都支持了DNSSEC。Unbound提供了一个这样的带DNSSEC验证机制的递归解析程序。

另外GFW的DNS劫持还可能被黑客利用、带来对国际国内互联网的严重破坏。一方面,GFW可能在一些紧急时刻按照“国家安全”的需要对所有DNS查询都进行污染,且可能指定污染后的IP为某个特定IP,使得全球网络流量的一部分直接转移到目标网络,使得目标网络立刻瘫痪。当然我们伟大的祖国郑重承诺“不率先使用核武器”…另一方面,GFW将伪造的DNS返回包要发送给源IP地址的源端口,如果攻击者伪造源IP,会怎样呢?将会导致著名的增幅攻击:十倍于攻击者发送DNS查询的流量将会返回给伪源IP,如果伪源IP的端口上没有开启任何服务,很多安全配置不严的系统就需要返回一条ICMP Port Unreachable消息,并且将收到的信息附加到这条ICMP信息之后;如果伪源IP的端口上开启了服务,大量的非法UDP数据涌入将使得伪源IP该端口提供的服务瘫痪。如果攻击者以1Gbps的速度进行查询,一个小型IDC(DNSpod被攻击事件)甚至一个地域的ISP也会因此瘫痪(暴风影音事件)。攻击者还可能设置TTL使得这些流量恰好通过GFW产生劫持响应,并在到达实际目标之前被路由丢弃,实现流量“空对空不落地”。攻击者还可能将攻击流量的目标IP设置伪造成与伪源IP有正常通信或者其他关联的IP,更难以识别。这样实际上就将一个国家级防火墙变成了一个国家级反射放大式拒绝服务攻击跳板

最为严重的是,这种攻击入门难度极低,任何一个会使用C语言编程的人只要稍微阅读libnet或者libpcap的文档,就可能在几天之内写出这样的程序。而GFW作为一套入侵防御系统,注定缺乏专门防范这种攻击的能力,因为如果GFW选择性忽略一些DNS查询不进行劫持,网民就有机可乘利用流量掩护来保证真正的DNS通信不被GFW污染。尤其是UDP这样一种无连接的协议,GFW更加难以分析应对。“反者道之动,弱者道之用。”

参考文献

  1. 闫伯儒, 方滨兴, 李斌, 王垚. "DNS欺骗攻击的检测和防范". 计算机工程, 32(21):130-132,135. 2006-11.
  2. Graham Lowe, Patrick Winters, Michael L. Marcus. The Great DNS Wall of China. 注:这篇文章虽然试图通过统计特性了解GFW,但由于实验条件控制不佳、实验结果观察不细致,加上缺乏对GFW的整体观,故没有提供什么有意义的结论。然而美国同学的这种科学态度与实验精神值得我们学习和思考。事实上,这篇文章仍然提供了珍贵的历史资料,读者不妨按照本文逻辑来分析这篇参考文献。阅读过这篇文献的敏感的读者还将在我们后续的文章中看到熟悉的数字。
  3. KLZ毕业. 入侵防御系统的评测和问题. 注:本文对DNS污染包的分类就是从这篇文章的分类继承而来。

深入理解 GFW:路由扩散技术

GFW的重要工作方式之一是在网络层的针对IP的封锁。事实上,GFW采用的是一种比传统的访问控制列表(Access Control List,ACL)高效得多的控制访问方式——路由扩散技术。分析这种新的技术之前先看看传统的技术,并介绍几个概念。

访问控制列表(ACL)

ACL可以工作在网络的二层(链路层)或是三层(网络层),以工作在三层的ACL为例,基本原理如下:想在某个路由器上用ACL控制(比如说是切断)对某个IP地址的访问,那么只要把这个IP地址通过配置加入到ACL中,并且针对这个IP地址规定一个控制动作,比如说最简单的丢弃。当有报文经过这个路由器的时候,在转发报文之前首先对ACL进行匹配,若这个报文的目的IP地址存在于ACL中,那么根据之前ACL中针对该IP地址定义的控制动作进行操作,比如丢弃掉这个报文。这样通过ACL就可以切断对于这个IP的访问。ACL同样也可以针对报文的源地址进行控制。如果ACL工作在二层的话,那么ACL控制的对象就从三层的IP地址变成二层的MAC地址。从ACL的工作原理可以看出来,ACL是在正常报文转发的流程中插入了一个匹配ACL的操作,这肯定会影响到报文转发的效率,如果需要控制的IP地址比较多,则ACL列表会更长,匹配ACL的时间也更长,那么报文的转发效率会更低,这对于一些骨干路由器来讲是不可忍受的。

路由协议与路由重分发

而GFW的网络管控方法是利用了OSPF等路由协议的路由重分发redistribution)功能,可以说是**“歪用”**了这个本来是正常的功能。

动态路由协议

说路由重分发之前先简单介绍下动态路由协议。正常情况下路由器上各种路由协议如OSPF、IS-IS、BGP等,各自计算并维护自己的路由表,所有的协议生成的路由条目最终汇总到一个路由管理模块。对于某一个目的IP地址,各种路由协议都可以计算出一条路由。但是具体报文转发的时候使用哪个协议计算出来的路由,则由路由管理模块根据一定的算法和原则进行选择,最终选择出来一条路由,作为实际使用的路由条目。

静态路由

相对于由动态路由协议计算出来的动态路由条目,还有一种路由不是由路由协议计算出来的,而是由管理员手工配置下去的,这就是所谓的静态路由。这种路由条目优先级最高,存在静态路由的情况下路由管理模块会优先选择静态路由,而不是路由协议计算出来的动态路由。

路由重分发

刚才说到正常情况下各个路由协议是只维护自己的路由。但是在某些情况下比如有两个AS(自治系统),AS内使用的都是OSPF协议,而AS之间的OSPF不能互通,那么两个AS之间的路由也就无法互通。为了让两个AS之间互通,那么要在两个AS之间运行一个域间路由协议BGP,通过配置,使得两个AS内由OSPF计算出来的路由,能通过BGP在两者之间重分发。BGP会把两个AS内部的路由互相通告给对方AS,两个AS就实现了路由互通。这种情况就是通过BGP协议重分发OSPF协议的路由条目。

另外一种情况,管理员在某个路由器上配置了一条静态路由,但是这条静态路由只能在这台路由器上起作用。如果也想让它在其他的路由器上起作用,最笨的办法是在每个路由器上都手动配置一条静态路由,这很麻烦。更好的方式是让OSPF或是IS-IS等动态路由协议来重分发这条静态路由,这样通过动态路由协议就把这条静态路由重分发到了其他路由器上,省去了逐个路由器手工配置的麻烦。

GFW路由扩散技术的工作原理

前面说了是“歪用”,正常的情况下静态路由是由管理员根据网络拓扑或是基于其他目的而给出的一条路由,这条路由最起码要是正确的,可以引导路由器把报文转发到正确的目的地。而GFW的路由扩散技术中使用的静态路由其实是一条错误的路由,而且是有意配置错误的。其目的就是为了把本来是发往某个IP地址的报文统统引导到一个**“黑洞服务器”**上,而不是把它们转发到正确目的地。这个黑洞服务器上可以什么也不做,这样报文就被无声无息地丢掉了。更多地,可以在服务器上对这些报文进行分析和统计,获取更多的信息,甚至可以做一个虚假的回应。

评价

有了这种新的方法,以前配置在ACL里的每条IP地址就可以转换成一条故意配置错误的静态路由信息。这条静态路由信息会把相应的IP报文引导到黑洞服务器上,通过动态路由协议的路由重分发功能,这些错误的路由信息可以发布到整个网络。这样对于路由器来讲现在只是在根据这条路由条目做一个常规报文转发动作,无需再进行ACL匹配,与以前的老方法相比,大大提高了报文的转发效率。而路由器的这个常规转发动作,却是把报文转发到了黑洞路由器上,这样既提高了效率,又达到了控制报文之目的,手段更为高明。

这种技术在正常的网络运营当中是不会采用的,错误的路由信息会扰乱网络。正常的网络运营和管控体系的需求差别很大,管控体系需要屏蔽的IP地址会越来越多。正常的网络运营中的ACL条目一般是固定的,变动不大、数量少,不会对转发造成太大的影响。而这种技术直接频繁修改骨干路由表,一旦出现问题,将会造成骨干网络故障。

所以说GFW是歪用了路由扩散技术,正常情况下没有那个运营商会把一条错误的路由信息到处扩散,这完全是歪脑筋。或者相对于正常的网络运营来说,GFW对路由扩散技术的应用是一种小聪明的做法。正常的路由协议功能被滥用至此,而且非常之实用与高效,兲朝在这方面真是人才济济。

GFW动态路由系统概括起来就是:人工配置(c)样本路由器(sr)的静态路由(r),向各ISP的出入口路由器(or)扩散此路由(r),将特定网络流量转到黑洞服务器(fs)进行记录。因此可以进行测量的项目有:

  • (r)被封锁的IP列表:可以通过协作报告机制收集用户报告,也可通过扫描著名站点获得;(传言:GFW动态路由系统的容量是几十万条规则)
  • (or)受到GFW影响的ISP出入口路由器:通过在广域多ISP内的节点协作traceroute可以测得;
  • (or)-(c)从关键词生效到动态路由生效的延迟:通过建立蜜罐并提交给GFW然后观察其响应;
  • (fs)黑洞服务器的健壮性:用伪源噪音流量对黑洞服务器进行填充,观测其响应。

参考文献

刘刚, 云晓春, 方滨兴, 胡铭曾. "一种基于路由扩散的大规模网络控管方法". 通信学报, 24(10): 159-164. 2003.

李蕾, 乔佩利, 陈训逊. "一种IP访问控制技术的实现". 信息技术, (6). 2001.

深入理解 GFW:HTTP URL/深度关键字检测

一项持续时间比张某还长的遗留研究。下面是它的开发研究简介,细节很多,非研究者可以略去不看。

HTTP URL/深度关键词检测

GFW的TCP协议阻断方式

GFW只根据单向的报文还原通信内容进行协议分析和关键词判断。并且在还原通信内容时,并不检查ack域的正确性,这也符合其“better is worse的设计哲学”,对于seq重叠的包,GFW的策略是忽略后来的包,因此利用GFW的这种流重组特性对其进行欺骗也十分容易。

一旦GFW根据还原出的内容检测到关键词,会根据触发关键词的包和关键词类型发送type1的RST或者type2的RST/ACK,在《入侵防御系统的评测和问题》中已经介绍,type2类型首次阻断中会先发送一组三个RST/ACK,序列号依次加1460、2920。type1与type2有所不同的是,type1首次阻断发送的RST的seq是关键词结束位置所在的包的ack,type2的seq则可能取为在此之前若干个包的ack,这可能与GFW处理报文的buffer大小和更新方式有关。在有些地区,单向发送内容触发type2关键词之后本地无法收到RST/ACK(对方可以收到),除非对方回复过任何设置了ACK选项的tcp包,另一些地区则本地总可以收到RST/ACK,原因还不清楚。这些问题希望有兴趣的读者自行研究。

特定情况下GFW还会伪造通信,例如type2的继发阻断中发送伪造的SYN/ACK企图劫持连接(为什么功能没有开发完全?),再如GFW的邮件检测模块对smtp协议的阻断会先伪造对方发送一条错误信息,再进行阻断。

URL关键词的检测

GFW的HTTP关键词检测模块的具体细节不是这里的重点,这里只回顾一些有关关键词检测的内容:

  • GFW有两种不相关的type、GFW结点的划分与TCP包的源端口无关、GFW时常有结点不工作、type1不工作的节点和type2不工作的结点不同。
  • URL关键词同样也有type1、type2之分。
  • 即使单向发送HTTP询问在一些地区可能无法收到GFW的type2 RST/ACK,实际上确实触发了关键词,会有90秒继发封锁。
  • 如果询问的格式是GET http://url HTTP/1.1\r\n\r\n,GFW进行关键词测试串的就是url。
  • 如果询问的格式是GET /url HTTP/1.1\r\nHost: hostname\r\n\r\n,GFW进行关键词测试的串就是.hostname/url。
  • GFW的HTTP URL关键词有普通的字符串关键词还有string1 && string2 && string3型的关键词,例如.google.com && great && firewall。只要url中包含这三个子串,无论出现的顺序如何,都会触发GFW。令人疑惑的是,string1*string2这种关键词匹配(在url中string1、string2顺序出现)判断实现起来要比string1 && string2容易得多,而目前已知的所有非普通关键词都是string1 && string2形式而不是string1*string2形式,是否存在string1*string2形式的关键词需要知道更多的URL关键词。

判断一个URL是否包含关键词的方法十分明了,选择一个跟本地IP分别在GFW两端的目标IP da,再任意选择一个不等于___的目标端口dp。对(da, dp)单向发送s;a;pa;s。(s = SYN; a = ACK; p = PSH)。为保证GFW按照顺序看到可以将每个包重复发送多遍,两组包间隔一定时间发送。如果触发了type1关键词可以收到GFW的r(RST),触发type2关键词可以收到GFW的sa。无sa或者无r,并不能说明不包含关键词,可能是GFW的相应结点不工作了。这时应该可以对此(da, dp)发送www.youtube.com来尝试触发。触发,说明原本确实没有关键词;否则说明GFW的相应类型的相应结点不工作了。

对关键词进行手工求解未免太过低效,利用GFW的单向报文检测特性,可以用来进行关键词检测的(da, dp)是几乎无穷多而且便于寻找的,让程序自动检测关键词非常可行。

  • 情况1、假定只有一个关键词。

  • 假设str长len,发起len个询问,第i个询问检测str去掉第i个字符形成的字符串。如果有阻断,说明这个字母可以去掉,否则说明这个字母不能去掉。询问完全并行。拿到所有结果之后可以立刻求出关键词。

  • 理想情况下只要1单位时间。

  • 情况2、假定所有关键词都是普通关键词,求出所有最小关键词。

  • 这种情况下可以进一步假定关键词是互不包含的子串,所以关键词可以定义前后关系。假设str长度为len,发起len个询问,第i个询问去掉前len + 1 - i个字符。求出最大的j使得在去掉前j个字符的情况下仍然有关键词。现在只需要求出从第j+1个字符开始的关键词,发起len - j个询问,第i个询问去掉后len - j + 1 - i个字符。现在求出最大的k使得去掉后k个字符仍然有关键词就完了。最后一个关键词就是str[j + 1..len - k],共花去2单位时间、询问。接下来处理str[1..len - k - 1] with hint: "开头位置 <= j",仍然是倒着测,有助于及时break。

  • 理想情况下时间等于关键词数目。

  • 为了减少(da, dp)的报废数目(短时间报废过多会被迫等待继发封锁结束),可以使用“二级索引”的办法:分sqrt(len)块,然后再精确到块内的位置。这样只是时间*2。

  • 情况3、&&型关键词、可能有多个,求出所有关键词。

  • 即使是求出其中的某一个关键词都是必须串行的,要花len的时间,难以忍受。但是实践中,.google.com && ** 和 search && ** 和 q=** 有可能同时是关键词,而询问作为www.google.com/search?q=**出现。由于此问题可由3-SAT规约到,是NPC问题,认为不可完成,所以从其它方面考虑:

  • 1. 根据经验假设只会出现2个&&,但实现带任意多&&的关键词的匹配算法上并不困难,GFW应该有相应的计算能力。

  • 2. 令s为{1..len}的一个随机置换,顺次考察s[i],如果去掉后仍然触发就去掉,不再触发就保留。最后可以得到一个关键词。多路并行应该就可以求出所有关键词了。尽管到达每个关键词的概率不均匀,实践效果应该可以接受。

深度检测关键词和其他关键词检测

GFW对所有通信进行了全文关键词检测,并且可以对gzip、deflate压缩的报文实现实时解压缩判断。进行这种关键词检测,需要事先准备好被测试文本。如果是某网页或者某文件含有深度检测关键词,需要将相应文件下载到本地。与测试URL关键字不同之处就是文件可以非常大。上面的方法几乎行不通。但我们希望先缩小关键词的寻找范围。希望根据GFW的r或者ra包的序列号来定位出现关键词的两个包,这样被检测字符串的长度就被缩小到了不到3000字节,就可以套用上面的方法了。

由于GFW的r和ra的seq是取自本地发出包的ack,只要对每个包按照发送顺序设置ack。

坑了(事实上)。

作者:GFW 技术评论