待月西厢下,迎风户半开。隔墙花影动,疑是玉人来。
最近 twitter 上最流行的一个关键词是”西厢计划”. 这个计划名字取得很浪漫,客户端叫做张生,对,就是西厢记里面那个翻墙去见崔莺莺小姐的张生;显然,服务器端必然叫做崔莺莺。客户端的张生是最重要的部件,可以不依赖于服务端工作。
我是个特别好奇的人,遇到好玩的总要学习一下看看是怎么弄的。因为西厢计划的作者只是简要的介绍了一下原理,其他报道又语焉不详,我当时就觉得很好奇,花了昨天一个晚上详细读了一下源代码,终于知道怎么回事了,觉得原理非常漂亮,所以写篇文章介绍总结一下。
先说大方向。大家都知道,连接被重置的本质,是因为收到了破坏连接的一个 TCP Reset 包。以前剑桥大学有人实验过,客户端和服务器都忽略 Reset, 则通信可以不受影响。但是这个方法其实只有理论价值,因为绝大多数服务器都不可能忽略 Reset 的 (比如 Linux, 需要 root 权限配置iptables, 而且这本身也把正常的 Reset 给忽略了)。只要服务器不忽略 Reset, 客户端再怎么弄都没用,因为服务器会停止发送数据,Reset 这条连接。所以,很多报道说西厢计划是忽略 Reset, 我从源代码来看应该不是这样。在我看来,西厢计划是利用了墙的一个可能的弱点–墙只在连接发起的时候把一个 TCP 连接加入监听序列,如果墙认为这个连接终止了,就会从监听序列中去掉这条记录,这样,这条连接上后续的包就不会被监听。西厢计划就是让墙“认为”这个连接终止的一个绝妙的方法。只要墙认为这个连接两端都是死老虎,墙就不会触发关键词检测,其后所有的数据,都不存在连接被重置的问题了。
如何让一个连接置之死地而后生,就是西厢计划那帮黑客神奇的地方了。这也不是一日之功。 首先,这帮牛人发现,墙的是一个入侵检测系统,把含有关键字的包当成一种“入侵”来对待。采取这种设计有很多好处,但缺点是入侵检测系统可能具有的问题,墙都可能有。西厢计划主页上那篇著名的论文就是讲这些七七八八的漏洞的。可以说处理这些七七八八的漏洞是非常困难的,迫使墙的设计者“拆东墙,补西墙”。这样补来补去,外表看起来好像很牛逼的墙,其实有很多本质上无法简单修补的漏洞,其中有一个致命的,就是 TCP 连接状态的判定问题。 出于入侵检测系统这种设计的局限,墙没有,也没办法准确判定一条 TCP 连接的状态,而只是根据两边收到的数据来“推测”连接的状态。而所有的关键词检测功能,都是基于“连接还活着”的这个推测的结果的。因为墙的规则是在连接发起的时候开始对这条连接的检测,在连接终止的时候停止对这条连接的检测,所以,一旦对连接的状态推测错误,把还活着的连接当成已经关闭的连接,墙就会放弃对这条连接上随后所有的包的检测,他们都会都透明的穿过墙的入侵检测。
上面只是想法,具体到 TCP 协议实现这一层,就要只迷惑墙,还不能触及我要通信的服务器。最理想的情况下,在任何有效通信之前,就能让墙出现错误判断,这些,就需要对 TCP 协议有深刻理解了。西厢计划的那帮黑客,居然真的去读 TCP 几百页的 RFC,还居然就发现了方法(这里我假设读者都知道 TCP 的三次握手过程和序列号每次加一的规则)。 我们都知道,三次握手的时候,在收到服务器的 SYN/ACK 的时候,客户端如果发送 ACK 并且序列号+1 就算建立连接了,但是客户端如果发送一个序列号没 +1 的 FIN (表示连接终止,但是服务器知道,这时候连接还没建立呢, FIN 这个包状态是错的,加上序列号也是错的,服务器自己一判断,就知道这个包是坏包,按照标准协议,服务器随手丢弃了这个包), 但这个包,过墙的时候,在墙看来,是表示连接终止的(墙是 ma de in china, 是比较山寨的,不维护连接状态,并且,墙并没有记下刚才服务器出去的 SYN/ACK 的序列号,所以墙不知道序列号错了)。所以,墙很高兴的理解为连接终止,舒了一口气去重置其他连接了, 而这个连接,就成了僵尸,墙不管你客户端了,而这时候,好戏才刚刚开始。
事实上,墙是双向检测的(或者说对每个包都检测的),因此,对服务器和客户端实现相同的对待方法,所以,墙不管客户端还不行,假如服务端有关键词传给客户端,墙还是有可能要发飙的(这里说有可能,因为我也不知道)。所以,最好的办法就是,让服务端也给墙一个终止连接的标志就好了。可是这个说起来简单,做起来难,怎么能让不受自己控制的服务器发一个自己想要的包呢? 西厢计划的那帮黑客,再次去读几百页的 RFC, 令人惊讶的发现,他们居然在 RFC 上发现了一个可以用的特性。我们上面说了,三次握手的时候,在收到 SYN/ACK 后,客户端要给服务器发送一个序列号+1 的ACK,可是,假如我不+1呢,直接发 ACK 包给服务器。 墙已经认为你客户端是死老虎了,不理你了,不知道你搞什么飞机,让这个 ACK 过了。可是服务器一看,不对啊,你给我的不是我期待的那个序列号, RFC 上说了,TCP 包如果序列号错了的话,就回复一个 Reset. 所以,服务器就回复了一个 Reset。这个 Reset 过墙的时候,墙一看乐了,服务器也终止连接了,好吧,两边都是死老虎了,我就不监听这条连接了。而至于客户端,这个服务器过来的 Reset 非常好识别,忽略就是。随后,客户端开始正确的发送 ACK, 至此,三次握手成功,真正的好戏开始,而墙则认为客户端和服务器都是死老虎,直接放过。所以,张生就这样透明的过了墙。 至于过墙以后所有的事情,《西厢记》里面都有记载,各位读者自行买书学习。
现在的西厢计划客户端,即“张生”模块的防连接重置的原理就是这样,服务器端,即莺莺模块的实现也是类似的。防DNS那个,不懂 DNS 协议,所以看不懂。我猜想,因为开发人员都是黑客,所以自然喜欢用最经得起折腾和高度定制的 Linux 开发。 现在看西厢计划的实现,因为依赖于 Linux 内核模块 netfilter, 在 Linux 上如鱼得水,但往其他平台的移植可能是个亟待解决的问题。 我觉得,在其他平台上,可以通过 libpcap 和 libnet ,在用户态实现相同的功能,就是有点麻烦而已,有兴趣的懂网络的可以照西厢计划原理,在家自行做出此功能;当然,全中国人民都用 Linux 最好 :)
PS 1: 据说是西厢计划一个作者画的原理图:http://img.ly/DIi
PS 2: 我对 TCP 的理解仅限于课本,如果上面的对技术的理解有错,请大家指出。
PS 3: 有些漏洞,可能是设计上本质缺陷,不是那么容易修复的。
PS 4: 除了最后一个图,本文没有其他相关链接,如需相关资料,自行 Google。
Pingbacks to ““西厢计划”原理小解”
74 comments to ““西厢计划”原理小解”
小强那边很容易就分析出来,主要原因在性能方面,我觉得照目前为止 要么大局域网 要么暂时不去管西厢类似方法。
我在考虑一个问题,如果发现你装死,就直接干掉你,这个改造的方案也开销也不是十分大,所以西厢计划只能绕过一时却不能绕过一世,也是悲剧啊。
一定要拿到合法证书(结婚证)才算数滴,所以要翻墙最终还是要靠加密链接
引用:「增加墙的负担 实际上就是增加人民的负担,毕竟人家party有的是钱,大不了花钱升级。 反抗越厉害,压制的力量也相应增强,而这就需要更多的钱,就需要更大程度压榨人民,而又导致更大的反抗,…」
看到他们这样说时候我也这样想的.以大多数人民做”后盾”来抵御少数翻墙者带来的压力,对他们来说太轻松了,感觉不到任何压力.
难怪未来有可能会推行白名单功能
re 耗子
出现过你那种情况,本来可以看一下下,然后再刷新被重置了。
虽然不懂具体技术,但看了LZ的文章,大概道理明白了,可怜偶一个windows下的小白。非常感谢技术牛人们。
好多木马啊楼主。。。
可以理解是什么意思,希望快点有Windows下的产品!
谢谢楼主的小解,很受用。另外木马就别挂了。。。
我表示GFW不是国产的,是cisco的,还有楼上说的cisco新路由器那个根本和GFW是两回事。。。
原理说的很明了啊。
博主啊,发现用360访问你的网站出现危险提示,一个什么XX.htm的文件有问题。
博主,你的博客好像被挂马了,地址 http://www.kmsjwg.******com******/******xx.****htm
无解。。。。。
中国封ip是主干路由扩散法。
3个网的出口都封。。。。。。
你数据可以进来但是国内的数据却出不去。
封ip不会大量采用的。因为bgp很恶心 太浪费cpu了
目前封ip除了 ghs永久封外 其他的ip都是针对p2p 下载关键字的东西来封的。
解除时间 10分钟
引用:
西厢 « Raymond said,
March 18, 2010 @ 10:05 am
[...] 看了篇文章,讲西厢计划的原理。基本上是懂得。疑问同留言的一样:如果直接封IP怎么办?封IP应该不是旁路的IDS吧? [...]
@luckspring:
记得给西厢的那些作者们 credit, 我只是看看代码写写文章而已,他们才是值得佩服的。
@阿莫西林
我的确没有验证过,也是看了源代码的原理猜测的。
@ocean
木马问题已经修复,谢谢!
哇,这么难的东西被你写的简单通俗易懂,佩服!我转载了一下希望楼主不要介意
“墙并没有记下刚才服务器出去的 SYN/ACK 的序列号,所以墙不知道序列号错了”
墙是记序列号的,可以通过触发墙规则并抓包进行测试。
太牛B了!mark一下!
其实我觉得墙要解决这个没有这么复杂,不用保持连接状态,用timer就行,遇到要rest的,记个timer,30秒内隔五秒就发送一次rst包,这个开销没有大很多。
@abadcafe
图和代码是不一样的,图是原理,代码是实现,你读源代码就明白我说的了。
@lvrenjia,
Thank you! My wordpress version was apparently too old.
@ocean,
Just fixed. Thank you. I think my wordpress version was too old (2.6.2).
光盘镜像已经出来了。
呵呵,我们公司刚好开发过这个监控系统 的一部分,这个系统 的确是一个旁路监控系统。拿北京来说,主干网上分出30%的光信号,再经过放大器,然后到达SSP负载均衡器,再后面就是华为那帮人的分析系统,如果判断非法就发reset包,由于这个速度一般会快于主干网的返回结果,所以客户端就被重置了,但有的时候,华为的服务器响应比主干网慢了,这样就导致了有时候高峰期你明明 看到网页结果了,但过几秒又被重置了,就是这个原理。上面所说的不管链接是否存活都监控,这个就目前来看,华为那帮人是办不到的,那样的话,他们的服务器肯定一下就挂了,因为数据量太大了
那帮牛人不可能把TCP/IP改了吧……
增加墙的负担 实际上就是增加人民的负担,毕竟人家party有的是钱,大不了花钱升级。 反抗越厉害,压制的力量也相应增强,而这就需要更多的钱,就需要更大程度压榨人民,而又导致更大的反抗,…
=========================
darasion said,
March 14, 2010 @ 11:01 pm
看了一下,发现。
简单的说:墙与张某人都是骗子,相互的骗,斗智斗勇的骗。
我再想,是不是有人能作出一个能够增加墙的负担的东西,不求马上解决问题,而是慢慢的把墙瓦解掉,比如:强迫那些本来不需要墙分析的东西必须仔细分析。
proxy+西厢 可以突破IP封锁
如果GFW在client第一次发SYN的时候就reset了怎么办(使用黑名单)?
RFC793: In the SYN-SENT state (a RST received in response
to an initial SYN), the RST is acceptable if the ACK field
acknowledges the SYN.
难道你们碰到的被reset情况很多么?
个人觉得现在99%都是直接封掉ip了吧!
LZ搞错了. 按照原理图, 事实上是这样:
client收到syn/ack以后发送一个rst先让GFW以为客户端半关闭了. 然后server忽略这个rst.
client再发一个错误的ack导致服务器也发送一个rst, GFW就以为连接全关闭了. 然后client忽略这个rst.
最后client发送一个正常的ack, server收到, 连接就建立了. 但GFW以为这个连接挂掉了.
这个只解决部分问题,GFW还有更简单的一招就是在IP这一层用黑名单直接屏蔽服务器,让你永远都连不过去。这个是最简单的也是最实用的。
思科已经新产品出来了。每秒135TB的真正防火墙。
张生只怕见不到莺莺了
+ 1
你135TB封我 ssh试试?
再说,实在不行,研究kad p2p试试
我感觉reset的情况不多了,大部分都是直接封IP
看来gfw应该很快就会补上这个洞
不过西厢却给了大家一个启发,就是从tcp协议底层去穿墙。西厢的意义是告诉我们,tcp协议的规则并不是无懈可击的,如果如病毒般出现好几个西厢变种,gfw立马就会变得无所适从。
是否可以这样理解——对GFW来说,此洞不补自己就成摆设,而“补上”就会给自己带来超大负担
小强小看不得。
小强知道偷懒。
小强很关心连接状态的,还会关心时序相关连接状态,额这 8.8.8.8 8.8.4.4 已经报废,换其它 dns 暂时有效。
我觉得一开始可能是黑客要攻击gfw,伪造get/?敏感词,让gwf去算,发现gwf还很聪明只检查有连接的
于是黑客放出西厢计划,让gwf改成全部都检查关键词
然后黑客伪造大量get,把gfw拖死
这个貌似在几个月前的某篇paper里就有了,不知道西乡计划的作者有没有给人家credit。
哦,原来这就是西厢计划。。。。似乎明白了一点。。
铁心搞局域网,直接剪断国际出口网线,看你怎么办
hacker47 这是。。。五毛?
不懂技术,瞎喊一句:张生是个好青年!
基本原理应该是“人民战争”,敬请升级gfw,我很乐观,哈哈
看了一下,发现。
简单的说:墙与张某人都是骗子,相互的骗,斗智斗勇的骗。
我再想,是不是有人能作出一个能够增加墙的负担的东西,不求马上解决问题,而是慢慢的把墙瓦解掉,比如:强迫那些本来不需要墙分析的东西必须仔细分析。
看不到。只是真不知道是不是会成为局域网。
铁心局域网了就开始做二层的东厢计划嘛。。看看BGP有没有什么漏洞之类的。。。哈哈。。。
本身就是个开源项目,原理也没有必要隐藏起来。再说的确如楼上所说,产品出来后一抓包就全明白了。
我只担心假设哪一天真是铁了心搞局域网拿怎么办?
武大郎服毒,喝也得死,不喝也得死。
“(墙是 ma de in china, 是比较山寨的,不维护连接状态,并且,墙并没有记下刚才服务器出去的 SYN/ACK 的序列号,所以墙不知道序列号错了)”
“不维护连接状态”这个不太可能吧, 现在哪家的放火强不维护连接状态啊
就netfilter的实现不也是依赖于connetion tracking的么
1、墙项目不是一有bug就能立刻打补丁,中间的流程不知道有多长
2、即使不开源,抓包就能分析原理,开源能使大家受益
3、有些系统架构的问题,使得bug修补异常痛苦,拆东墙补西墙
其主页上,表示Windows移植版本已经alpha了呀。
不会存在很难处理的问题。如果在IDS实现一个相对完整的协议栈呢?
我在cable接入的环境下测试西厢结果是,扰乱的RST包没有发挥作用,墙还是发过来了RST包。不过墙的自动机还是有问题,当我把所有的RST包都丢掉后,它就一直不停地给我发握手的包。看样子墙是打算一开始把握手就接管过来。
有漏洞!如果墙一直不停发包,那么就显然增加了墙的负担(带宽和处理能力),如果大家一起发这个包,而且简单的一分钟发2K个,墙就准备Overload了。
adreaman said,
March 14, 2010 @ 7:46 pm
Cisco的墙(无论PIX还是ASA)都是基于连接状态的,每个包都得有TCP状态才能过。一般稍微专业点的厂商的产品也都是如此。
你有点错误 pix和asa 是路由式或者说是交换机式 也就是说ip数据包经过这台机器才能到达别的机器
而gfw 是ids原理 就是监听线路上的数据 然后发送 rst 去中断 tcp链接。
如果gfw是转发数据包 的话为什么还会让我们收到正确的dns数据包呢? 而不直接drop掉那个dns数据包然后发送一个错误的呢
或者是发rst的呢 而不直接drop数据包呢。
这就是因为gfw是监听式的 只能靠发包来中断连接。
windows不好实现的原因就是win 不给底层权限 除非你自己写驱动。。。
dns如果是在没有iptables丢包的话 可以采取其他方法获得正确ip 但是需要建立一个服务器了。
给你补充一些dns模块吧。最近我也研究了一下墙的dns 模块。就像张某说的那样
dns污染分为2种类型 一种是 什么都是固定值的 另外一种是随机的 称为2型。 2型的发3个包 1型的发1个包 2型不匹配 @系列的域名(比如baidu.com) dns污染的ip有限。 dns模块的原理就是 匹配ip地址 然后给iptables加个模块 识别gfw发出的dns污染 包 然后drop掉 。这样就可以通过 正确的dns包了。
我要在Ubuntu下试试,说来很兴奋
没法同意大牛你更多了…
不是墙不愿意补上这洞,实际上我们说的墙和真正的防火墙是有非常大的区别,真正的防火墙是在线部署的方式,就是串接在链路上。而GFW其实一个旁路的IDS,通过reset包来进行阻断,所以它并没有像真正的防火墙一样维护一个状态表,所以可以采用西厢计划中的方式绕过。如果GFW为了补上这个洞采用串接的部署方式基本上是不可能的,目前防火墙根本无法达到这个性能要求,而且阻断策略的配置也异常的麻烦。
有些东西我就不点明了,请上面觉得墙很容易这样修那样补的同学自己回家思考如果墙这样修补的副作用。有些事情往往表面上看是修长城,其实是自埋炸弹。我想西厢的作者之所以敢直接开源,是自信可能的后果的。
Cisco的墙(无论PIX还是ASA)都是基于连接状态的,每个包都得有TCP状态才能过。一般稍微专业点的厂商的产品也都是如此。
不是王道~
事实上,按照这个原理来看,补上这个漏洞并不难,只要对这个原理提起了重视,而且增加的负担也不大。因为原本就是所有数据都会被分光走一下,那么现在墙如果XXX的话,就搞定了,负担增加也不大。
出于合理原因省略XXX的内容,相信看得懂原理的人,也大概能猜出来,墙可以做的修补吧。
不懂协议,等西厢计划移植到MAC再去测试。
我所不解的是,如果他们这样一公开,墙马上就补这个漏洞,这个计划岂不又game over
那些泥瓦匠知道西厢原理后会不会出针对性的方案?
比如每个TCP连接不管死活,在一个timer expire之前都进行检测。
把这个总结出来未免便宜了gfw的人吧。最起码也要让他们花上几天功夫读代码才行啊。这个应该暂时作为秘密保护起来
我看未必,墙方还是能够维护的起高额的技术聘请费的,思科的技术过来吃顿饭就解决的问题。
问题是这样只能让墙方更加强维护填补漏洞,不能解决根本。最好是利用墙的本质让墙陷入回路中瘫痪,而且要最初级的,像当初lion组织的ddos攻击白宫一样,人口基数优势。
不知道在 Mac 下安装怎么样,尝试中。
让人奇怪的是,tcp/ip居然是这样,都互相发送了rst,之后还继续接受ack包