V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
AlexaZhou
V2EX  ›  站长

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

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

    背景

    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   ·   我们的愿景   ·   实用小工具   ·   2304 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 07:15 · PVG 15:15 · LAX 00:15 · JFK 03:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.