当前位置 主页 > 服务器问题 > nginx问题汇总 >

    Nginx服务器抵御CC攻击的相关配置讲解(3)

    栏目:nginx问题汇总 时间:2018-10-24 10:36

    那么我们要如何来做这个请求频率的限制呢?

    首先,我们先要一个攻击者无法杜撰的sessionID,一种方式是用个池子记录下每次给出的ID,然后在请求来的时候进行查询,如果没有的话,就拒绝请求。这种方式我们不推荐,首先一个网站已经有了session池,这样再做个无疑有些浪费,而且还需要进行池中的遍历比较查询,太消耗性能。我们希望的是一种可以无状态性的sessionID,可以吗?可以的。

    rewrite_by_lua '   local random = ngx.var.cookie_random   if(random == nil) then     random = math.random(999999)   end   local token = ngx.md5("opencdn" .. ngx.var.remote_addr .. random)   if (ngx.var.cookie_token ~= token) then     ngx.header["Set-Cookie"] = {"token=" .. token, "random=" .. random}     return ngx.redirect(ngx.var.scheme .. "://" .. ngx.var.host .. ngx.var.uri)   end';

    大家是不是觉得好像有些眼熟?是的,这个就是上节的完美版的配置再加个随机数,为的是让同一个IP的用户也能有不同的token。同样的,只要有nginx的第三方模块提供散列和随机数功能,这个配置也可以不用lua直接用纯配置文件完成。

    有了这个token之后,相当于每个访客有一个无法伪造的并且独一无二的token,这种情况下,进行请求限制才有意义。

    由于有了token做铺垫,我们可以不做什么白名单、黑名单,直接通过limit模块来完成。

    http{   ...   limit_req_zone $cookie_token zone=session_limit:3m rate=1r/s;}

    然后我们只需要在上面的token配置后面中加入

    limit_req zone=session_limit burst=5;

    于是,又是两行配置便让nginx在session层解决了请求频率的限制。不过似乎还是有缺陷,因为攻击者可以通过一直获取token来突破请求频率限制,如果能限制一个IP获取token的频率就更完美了。可以做到吗?可以。

    http{   ...   limit_req_zone $cookie_token zone=session_limit:3m rate=1r/s;   limit_req_zone $binary_remote_addr $uri zone=auth_limit:3m rate=1r/m;}location /{   limit_req zone=session_limit burst=5;   rewrite_by_lua '   local random = ngx.var.cookie_random   if (random == nil) then     return ngx.redirect("/auth?url=" .. ngx.var.request_uri)   end   local token = ngx.md5("opencdn" .. ngx.var.remote_addr .. random)   if (ngx.var.cookie_token ~= token) then     return ngx.redirect("/auth?url=".. ngx.var.request_uri)   end';}location /auth {   limit_req zone=auth_limit burst=1;   if ($arg_url = "") {     return403;   }   access_by_lua '     local random = math.random(9999)     local token = ngx.md5("opencdn" .. ngx.var.remote_addr .. random)     if (ngx.var.cookie_token ~= token) then       ngx.header["Set-Cookie"] = {"token=" .. token, "random=" .. random}       return ngx.redirect(ngx.var.arg_url)     end   ';}

    我想大家也应该已经猜到,这段配置文件的原理就是:把本来的发token的功能分离到一个auth页面,然后用limit对这个auth页面进行频率限制即可。这边的频率是1个IP每分钟授权1个token。当然,这个数量可以根据业务需要进行调整。

    需要注意的是,这个auth部分我lua采用的是access_by_lua,原因在于limit模块是在rewrite阶段后执行的,如果在rewrite阶段302的话,limit将会失效。因此,这段lua配置我不能保证可以用原生的配置文件实现,因为不知道如何用配置文件在rewrite阶段后进行302跳转,也求大牛能够指点一下啊。