CC 攻击的防御(-)通过 Cookie 抵挡 CC 攻击 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
AlexaZhou
V2EX    站长

CC 攻击的防御(-)通过 Cookie 抵挡 CC 攻击

  •  
  •   AlexaZhou 2016-03-02 09:03:02 +08:00 17072 次点击
    这是一个创建于 3515 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    CC 攻击发生在 TCP/IP 协议的第七层,一般方式是在很短的时间里对网站发起大量请求,消耗目标服务器的资源,使目标网站负载过高而不能访问。

    CC 攻击和 UDP Flood, TCP SYN Flood 这类位于 TCP/IP 第四层的攻击相比,对自己的资源消耗更少,对服务器的攻击强度更高,有四两拨千斤的效果。如果防御不好,呵呵,一台笔记本打垮一整个服务器集群也不是不可能。

    而一般人对网络攻击是怎样进行的,以及怎样进行防御了解的都不多,这也就给了攻击者可乘之机。我这段时间在开发 VeryNginx ,对这部分正好有所研究。于是写成《 CC 攻击的防御》系列文章,主要探讨 CC 攻击的原理,以及一些可能的防御思路。希望能对大家有所帮助,如同在我无知的时候,互联网上其他无私分享知识给我的人一样。

    文中描述的全部方法都已经编写成代码,并实际测试通过,包含在开源项目 VeryNginx 中。开箱即可使用,并且还包含其他诸多强大功能。

    传送门: https://github.com/alexazhou/VeryNginx

    攻击方式

    为了进行防御,我们首先要了解我们对手的攻击方式。

    通常发起 CC 攻击是使用专门的攻击工具,同时模拟成多个用户,向目标网站发起多个请求,一般这些软件为了防止地址被屏蔽,还内置通过代理攻击的功能。可以通过多个代理服务器对目标发起攻击,使封 IP 的防御方式变的失效。

    防御思路

    因为 CC 攻击通过工具软件发起,而普通用户通过浏览器访问,这其中就会有某些区别。想办法对这二者作出判断,选择性的屏蔽来自机器的流量即可。

    初级

    普通浏览器发起请求时,除了要访问的地址以外, Http 头中还会带有 Referer , UserAgent 等多项信息。遇到攻击时可以通过日志查看访问信息,看攻击的流量是否有明显特征,比如固定的 Referer 或 UserAgent ,如果能找到特征,就可以直接屏蔽掉了。

    中级

    如果攻击者伪造了 Referer 和 UserAgent 等信息,那就需要从其他地方入手。攻击软件一般来说功能都比较简单,只有固定的发包功能,而浏览器会完整的支持 Http 协议,我们可以利用这一点来进行防御。

    首先为每个访问者定义一个字符串,保存在 Cookies 中作为 Token ,必须要带有正确的 Token 才可以访问后端服务。当用户第一次访问时,会检测到用户的 Cookies 里面并没有这个 Token ,则返回一个 302 重定向,目标地址为当前页面,同时在返回的 Http 头中加入 set cookies 字段,对 Cookies 进行设置,使用户带有这个 Token 。

    客户端如果是一个正常的浏览器,那么就会支持 http 头中的 set cookie 和 302 重定向指令,将带上正确的 Token 再次访问页面,这时候后台检测到正确的 Token ,就会放行,这之后用户的 Http 请求都会带有这个 Token ,所以并不会受到阻拦。

    客户端如果是 CC 软件,那么一般不会支持这些指令,那么就会一直被拦在最外层,并不会对服务器内部造成压力。

    高级

    高级一点的,还可以返回一个网页,在页面中嵌入 Javascript 来设置 Cookies 并跳转,这样被伪造请求的可能性更小

    Token 生成算法

    Token 需要满足以下几点要求

    • 每个 IP /客户端的 Token 不同
    • 无法伪造
    • 一致性,即对相同的客户端,每次生成的 Token 相同

    Token 随 IP 地址变化是为了防止通过一台机器获取 Token 之后,再通过代理服务来进行攻击。一致性则是为了避免在服务器端需要存储已经生成的 Token 。

    推荐使用以下算法生成 Token ,其中 Key 为服务器独有的保密字符串,这个算法生成的 Token 可以满足以上这些要求。

    Token = Hash( UserAgent + client_ip + key )

    43 条回复    2016-06-17 16:42:26 +08:00
    Yamade
        1
    Yamade  
       2016-03-02 09:03:51 +08:00   1
    我去.....我抱你大腿...
    qcloud
        2
    qcloud  
       2016-03-02 09:05:33 +08:00
    一般安全软件都可以搞定
    jkjoke
        3
    jkjoke  
       2016-03-02 09:05:34 +08:00   1
    学习了
    irainsoft
        4
    irainsoft  
       2016-03-02 09:11:19 +08:00   1
    收藏膜拜(;;;;;°°)
    c0o1
        5
    c0o1  
       2016-03-02 09:16:21 +08:00   1
    给正常流量打了个标签
    soolby
        6
    soolby  
       2016-03-02 09:28:47 +08:00   1
    周大神,你好
    tftk
        7
    tftk  
       2016-03-02 09:32:18 +08:00   1
    Cookie 和 Token 不是用来做防攻击的,只能在攻击力量很弱的时候起一点作用。
    tabris17
        8
    tabris17  
       2016-03-02 09:33:24 +08:00
    useless
    AlexaZhou
        9
    AlexaZhou  
    OP
       2016-03-02 09:38:50 +08:00 via iPhone
    @tftk 愿闻其详
    H3x
        10
    H3x  
       2016-03-02 09:45:57 +08:00
    楼主,提一下我的看法哈,不一定正确
    假定攻击者使用一对 useragent 和 clientip 向服务器发起不带 cookie 的请求,然后在返回的应答包中取出 set cookies 中的 token 值,再赋到用于攻击请求的 cookie 中,这样是不是可以符合服务器对 token 的校验?
    接着替换 useragent 和 clientip ,获取到 token 后再发起攻击请求,如果循环。
    H3x
        11
    H3x  
       2016-03-02 09:51:22 +08:00
    相对于传统的 cc 攻击,只发出攻击请求
    针对你的防御措施,攻击者只需要多出“获取 token ,再赋到攻击请求”这么一步
    jarlyyn
        12
    jarlyyn  
       2016-03-02 10:06:05 +08:00
    固定 cookie 就可以了, token 毫无必要。

    能获取固定的 cookie,获取你的 token 也不难。
    scarlex
        13
    scarlex  
       2016-03-02 10:07:01 +08:00   2
    文章睇一段, TCP/IP 不是只有四层么?七层那个是 OSI 吧
    AlexaZhou
        14
    AlexaZhou  
    OP
       2016-03-02 10:29:28 +08:00
    @H3x
    如果要进行一次 CC 攻击,过程一般是这样,连接一个代理服务器,发送 http 请求,然后立刻断开连接。这里断开是为了避免受到服务器的回包,因为服务器通常带宽很大,回包都过来的话容易把自己堵死。

    网上随便就能下载到很多攻击软件,大概行为模式都是这样。

    在添加了一次 Token 验证之后,这类攻击软件就基本不可用了,如果想发起攻击,就只能从头开始编写专门的工具,在普通攻击的方式上完成 Cookies 验证这一步。但具体来说,攻击者在编写这个工具的过程中还需要实现多线程(或者异步),以及通过代理服务器进行连接这些特性,才可以发起一定强度的攻击。

    对于通过返回一个网页,然后通过 Javascript 设置 cookies 的情况,这样攻击工具可能还需要外挂一个 js 的执行环境...

    效果就是发起一次攻击的成本大大增加了。

    实际上也并没有绝对的防御方式,我们所能做的也就是不断提高攻击者的成本。
    AlexaZhou
        15
    AlexaZhou  
    OP
       2016-03-02 10:35:53 +08:00
    @H3x @jarlyyn

    唯一的 Token 限制了必须能收到回包才可以继续访问。

    如果通过多个代理服务器进行攻击

    固定 cookies 的情况下,只需要把 cookies 提取出来,然后攻击步骤是:
    连接代理->发送请求->断开连接 的过程,

    唯一 Token 的情况:
    连接代理->发送请求->收到回包->解析包获取 Token->再次发送攻击请求->断开连接

    这样攻击的速度会大大降低。
    AlexaZhou
        16
    AlexaZhou  
    OP
       2016-03-02 10:36:57 +08:00
    @soolby

    太抬举了
    AlexaZhou
        17
    AlexaZhou  
    OP
       2016-03-02 10:48:57 +08:00
    @scarlex

    啊,不要在意这些细节
    scarlex
        18
    scarlex  
       2016-03-02 10:49:45 +08:00   1
    @AlexaZhou

    :smile: 看第一段就觉得不对劲嘛!
    lecher
        19
    lecher  
       2016-03-02 11:00:14 +08:00 via Android   3
    实际上 token 只能挡普通攻击,计算 token 这个事情本身就消耗 CPU 资源,攻击的时候为了省带宽也有只发不收的。
    这个 token 的校验有用,只要入口带宽没有被塞满,普通 cc 攻击都可以挡住。

    但是如果请求被塞满入口带宽都爆掉的时候,有可能服务器自己算校验就把 CPU 爆掉了。

    此外,做太复杂的校验对搜索引擎不够友好,这 token 校验第一波挡住的怕是搜索引擎的爬虫吧。
    AlexaZhou
        20
    AlexaZhou  
    OP
       2016-03-02 11:15:27 +08:00
    @lecher

    对的,这个就是针对 CC 攻击的一种防御思路,通过这个手段把不合法流量拦住。

    对于暴力发包,只发不收的攻击来说,带宽都满了,并并不能通过这种方式进行防御。

    生成 Token 的资源消耗还好,我在单核心的虚拟机中测试 VeryNginx ,同时运行 ab 和 VeryNginx ,性能在 6000 Qps 左右,实际上 nginx 单个 Worker 可能可以跑到 1W Qps 。
    AlexaZhou
        21
    AlexaZhou  
    OP
       2016-03-02 11:16:32 +08:00
    @lecher

    拦住搜索引擎是个问题,最好只是在被攻击的时候开启这个功能,平时关闭掉
    jarlyyn
        22
    jarlyyn  
       2016-03-02 11:40:12 +08:00
    @AlexaZhou

    我用过这个方法,而且是用的带 html 的 js 的。

    同时我自己也写过简单的爬虫。用 phantomjs 之类的话,所有无痕的方式基本都没有用。

    如果只是普通的 curl 的话,那么 html 静态页+固定 cookie 也足够了。大不了定时修改一下。

    http://blog.jarlyyn.com/site/blogi/100
    AlexaZhou
        23
    AlexaZhou  
    OP
       2016-03-02 11:49:00 +08:00
    @jarlyyn

    对 CC 攻击者来说,在使用固定或者唯一 Token 的情况下,攻击成本是有差别的。

    很多攻击软件是可以设置 http 头的,如果使用固定 Token ,攻击者只需要在本机获取一次 Token ,然后设置好 http 头就可以直接发起攻击了,攻击成本低的可以...

    但是如果使用可变 Token ,基本市面上所有 CC 软件全都无法使用了

    这样就需要使用 phantomjs 这类的软件,这类工具一般是设计用来作为爬虫的,对攻击来说,速度太慢了
    willis
        24
    willis  
       2016-03-02 13:15:28 +08:00 via iPhone   1
    这不就是 opencdn 的做法嘛 nginx +lua
    AlexaZhou
        25
    AlexaZhou  
    OP
       2016-03-02 13:18:48 +08:00
    @willis

    可能是,好像加速乐也有这样的防护措施

    主要是一般人对这个都不怎么了解,写出来科普一下
    yanyandenuonuo
        26
    yanyandenuonuo  
       2016-03-02 13:44:24 +08:00   1
    Token = Hash( UserAgent + client_ip + key )
    一个局域网内两台相同配置的机器使用同一版本浏览器访问那 UserAgent 和 client_ip 应该都一样了吧
    woodrat
        27
    woodrat  
       2016-03-02 13:44:58 +08:00   1
    还可以 302 到一个验证码页面
    AlexaZhou
        28
    AlexaZhou  
    OP
       2016-03-02 13:47:58 +08:00
    @yanyandenuonuo

    这种情况 Token 是一样的
    AlexaZhou
        29
    AlexaZhou  
    OP
       2016-03-02 13:48:13 +08:00
    @woodrat

    嗯,可以的
    Strikeactor
        30
    Strikeactor  
       2016-03-02 13:58:24 +08:00   1
    和防爬虫一个道理, token 放一部分到前端去生成,同时函数加密,攻击者只有自己实现一遍 token 生成函数和在服务器上跑 JS 两种选择,成本都不小

    不过我还是更倾向于 Nginx 限制高并发,结合防火墙直接 ban 掉高并发的 IP 。毕竟 CC 的 IP 一般不会太多,有大量 IP 资源的估计就直接 D 了
    brance
        31
    brance  
       2016-03-02 14:06:08 +08:00 via iPhone   1
    666
    AlexaZhou
        32
    AlexaZhou  
    OP
       2016-03-02 14:17:26 +08:00
    @Strikeactor

    非常赞同。

    Nginx 限制并发也是一种很好的防御方式,实际上我倾向多种防御方式结合使用,单一的防御方式总有被攻击者绕过的可能性,混合策略就很难绕过,防御效果会比较好

    PS :后续也打算在 VeryNginx 中加入根据请求频次进行屏蔽的防御方式
    x14oL
        33
    x14oL  
       2016-03-02 14:21:59 +08:00   1
    @AlexaZhou python 大法好,写一个多进程异步加代理的 cc 工具其实成本不高的。
    AlexaZhou
        34
    AlexaZhou  
    OP
       2016-03-02 14:35:09 +08:00
    @x14oL

    如果自己写一个工具,还需要实现:

    1 ,能通过多个代理服务器来发起请求,不然单 IP 很容易被封掉
    2 ,对于通过 Javascript 来设置 cookies 的,需要外挂一个 js 的执行环境,或者读懂 js 的算法,并在 Python 里实现一次

    总之成本还是不低
    AlexaZhou
        35
    AlexaZhou  
    OP
       2016-03-02 14:35:39 +08:00
    @x14oL

    ps :我也是 Python 党
    Yamade
        36
    Yamade  
       2016-03-02 14:42:36 +08:00   1
    我有一个问题:如果 VeryNginx 前面套了一个 cdn 的话,然后攻击者强制使用清除缓存的头,那么 VeryNginx 是不是把 cdn 的节点拦截了?
    lhbc
        37
    lhbc  
       2016-03-02 14:52:11 +08:00 via Android   1
    @Yamade 这种方式不适合跑在 CDN 后面
    AlexaZhou
        38
    AlexaZhou  
    OP
       2016-03-02 14:58:51 +08:00
    Yamade

    会,这种浏览器行为检测会无差别的拦截非浏览器流量, cdn 应该也会被拦截到

    如果在有 CDN 的情况下使用这种防御方式,应该需要在逻辑中加入专门的规则来放过来自 CDN 的请求

    一种方式是由请求路径来判断,一般来说放在 CDN 的是静态文件,而针对静态文件作 CC 攻击是没有太大意义的,所以可以判断如果是静态文件的路径,就不进行这个检测。此外还可以根据 IP 或者 CDN 服务器特有的请求头(如果有的话)来判断

    VeryNginx 的话本身支持定义复合规则来匹配请求,所以简单配置就可以做到这一点,并不需要另外编写代码

    最后就是使用强制清除缓存的 Http 请求头,并不一定能使 CDN 服务器发出回源请求吧?
    Slienc7
        39
    Slienc7  
       2016-03-02 15:05:02 +08:00   1
    很久之前就这么做了,不过我是用来防止蜘蛛的...
    AlexaZhou
        40
    AlexaZhou  
    OP
       2016-03-02 16:10:20 +08:00
    @xgowex

    ,可怜的蜘蛛就掉坑里爬不出来了
    Yamade
        41
    Yamade  
       2016-03-02 17:16:16 +08:00
    @AlexaZhou 谢谢回复.清除缓存的 Http 请求头 百度和 cloudflare 是回源的.我的攻击就是这样.逼得我全部缓存了.
    wujunze
        42
    wujunze  
       2016-03-02 22:20:44 +08:00
    学习了
    xuboying
        43
    xuboying  
       2016-06-17 16:42:26 +08:00
    由于代理不稳定的原因,还是可能在出现普通用户访问的时候切换代理的场景,这种机制最好在受到攻击的时候才开启。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3003 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 13:06 PVG 21:06 LAX 06:06 JFK 09:06
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86