通过nginx配置文件抵御攻击
0x00 前言
大家好,我们是OpenCDN团队的Twwy。这次我们来讲讲如何通过简单的配置文件来实现nginx防御攻击的效果。 其实很多时候,各种防攻击的思路我们都明白,比如限制IP啊,过滤攻击字符串啊,识别攻击指纹啦。可是要如何去实现它呢?用守护脚本吗?用PHP在外面包一层过滤?还是直接加防火墙吗?这些都是防御手段。不过本文将要介绍的是直接通过nginx的普通模块和配置文件的组合来达到一定的防御效果。
0x01 验证浏览器行为
简易版
我们先来做个比喻。社区在搞福利,在广场上给大家派发红包。而坏人派了一批人形的机器人(没有语言模块)来冒领红包,聪明工作人员需要想出办法来防止红包被冒领。 于是工作人员在发红包之前,会给领取者一张纸,上面写着“红包拿来”,如果那人能念出纸上的字,那么就是人,给红包,如果你不能念出来,那么请自觉。于是机器人便被识破,灰溜溜地回来了。是的,在这个比喻中,人就是浏览器,机器人就是攻击器,我们可以通过鉴别cookie功能(念纸上的字)的方式来鉴别他们。下面就是nginx的配置文件写法。
1
2
3
4 |
if ($cookie_say != "hbnl" ){ add_header Set-Cookie "say=hbnl" ; rewrite .* "$scheme://$host$uri" redirect; } |
增强版
仔细的你一定会发现配置文件这样写还是有缺陷。如果攻击者设置cookie为say=hbnl(CC攻击器上就可以这么设置),那么这个防御就形同虚设了。我们继续拿刚刚那个比喻来说明问题。坏人发现这个规律后,给每个机器人安上了扬声器,一直重复着“红包拿来,红包拿来”,浩浩荡荡地又来领红包了。 这时,工作人员的对策是这样做的,要求领取者出示有自己名字的户口本,并且念出自己的名字,“我是xxx,红包拿来”。于是一群只会嗡嗡叫着“红包拿来”的机器人又被撵回去了。 当然,为了配合说明问题,每个机器人是有户口本的,被赶回去的原因是不会念自己的名字,虽然这个有点荒诞,唉。然后,我们来看下这种方式的配置文件写法
1
2
3
4 |
if ($cookie_say != "hbnl$remote_addr" ){
add_header Set-Cookie "say=hbnl$remote_addr" ;
rewrite .* "$scheme://$host$uri" redirect; } |
完美版
那么要如何根据他们自身的信息得出他们又得出他们算不出的数值? 我想,聪明的你一定已经猜到了,用salt加散列。比如md5("opencdn$remote_addr"),虽然攻击者知道可以自己IP,但是他无法得知如何用他的IP来计算出这个散列,因为他是逆不出这个散列的。当然,如果你不放心的话,怕cmd5.com万一能查出来的话,可以加一些特殊字符,然后多散几次。 很可惜,nginx默认是无法进行字符串散列的,于是我们借助nginx_lua模块来进行实现。
1
2
3
4
5
6
7 |
rewrite_by_lua '
local say = ngx.md5( "opencdn" .. ngx.var.remote_addr)
if (ngx.var.cookie_say ~= say) then
ngx.header[ "Set-Cookie" ] = "say=" .. say
return ngx.redirect(ngx.var.scheme .. "://" .. ngx.var.host .. ngx.var.uri)
end '; |
0x02 请求频率限制
不得不说,很多防CC的措施是直接在请求频率上做限制来实现的,但是,很多都存在着一定的问题。 那么是哪些问题呢? 首先,如果通过IP来限制请求频率,容易导致一些误杀,比如我一个地方出口IP就那么几个,而访问者一多的话,请求频率很容易到上限,那么那个地方的用户就都访问不了你的网站了。 于是你会说,我用SESSION来限制就有这个问题了。嗯,你的SESSION为攻击者敞开了一道大门。为什么呢?看了上文的你可能已经大致知道了,因为就像那个“红包拿来”的扬声器一样,很多语言或者框架中的SESSION是能够伪造的。以PHP为例,你可以在浏览器中的cookie看到PHPSESSIONID,这个ID不同的话,session也就不同了,然后如果你杜撰一个PHPSESSIONID过去的话,你会发现,服务器也认可了这个ID,为这个ID初始化了一个会话。那么,攻击者只需要每次发完包就构造一个新的SESSIONID就可以很轻松地躲过这种在session上的请求次数限制。 那么我们要如何来做这个请求频率的限制呢? 首先,我们先要一个攻击者无法杜撰的sessionID,一种方式是用个池子记录下每次给出的ID,然后在请求来的时候进行查询,如果没有的话,就拒绝请求。这种方式我们不推荐,首先一个网站已经有了session池,这样再做个无疑有些浪费,而且还需要进行池中的遍历比较查询,太消耗性能。我们希望的是一种可以无状态性的sessionID,可以吗?可以的。
1
2
3
4
5
6
7
8
9
10
11
12
13 |
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 '; |
1
2
3
4 |
http{
...
limit_req_zone $cookie_token zone=session_limit:3m rate=1r /s ; } |
1 |
limit_req zone=session_limit burst=5; |
1
2
3
4
5 |
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 ; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 |
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 = "" ) { return 403; } 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 '; } |
0x03 防扫描
ngx_lua_waf模块 这个是一个不错的waf模块,这块我们也就不再重复造轮子了。可以直接用这个模块来做防护,当然也完全可以再配合limit模块,用上文的思路来做到一个封IP或者封session的效果。
0x04 总结
本文旨在达到抛砖引玉的作用,我们并不希望你直接单纯的复制我们的这些例子中的配置,而是希望根据你的自身业务需要,写出适合自身站点的配置文件。
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
选择AiDeep,让人工智能为你工作:http://www.aideep.com/
四季很好,只要有你,文娱排行榜:http://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 河北新增32例本土确诊病例 4823429
- 2 美国"制裁"港府官员 驻港公署驳斥 4654609
- 3 特朗普脸书账号和Ins账号被"解封" 4491698
- 4 河北邢台南宫实行最严厉封控 4334488
- 5 韩国网红Hamzy点赞辱华言论后道歉 4182781
- 6 北京一确诊病例第7次核酸检测阳性 4036384
- 7 长春新增新冠肺炎确诊病例3例 3895110
- 8 民警办案时强奸女性获刑4年半 3758781
- 9 外媒:特朗普将为自己举办告别仪式 3627224
- 10 山西发现周代女性化妆品盒 3500271