前天,服务器突然异常高负荷运行
查看日志,惊呆了,这样一个小站点居然产生了100M的日志?
日志分析,一位来自内蒙古呼和浩特市的116.114.21.*的这位网友,对网站进行了锲而不舍的漏洞扫描。累计扫描次数可能有30万次?
服务器性能很菜,麻烦大哥扫描能不能加上点限制,比如每秒扫一次之类的。。。
估计这位仁兄可能看不到这篇文章,我们对服务器进行一些改造吧!搞一个CC防火墙~
首先保证你的Nginx的Lua模块正常安装,如果没有安装,请百度一下【Nginx安装lua-nginx-module】
接着,写一个配置文件:cc.conf
lua_shared_dict limit 10m;
lua_package_path "/nginx/waf/?.lua";
init_by_lua_file /nginx/waf/cc.lib.lua;
access_by_lua_file /nginx/waf/cc.lua;
注意:/nginx/waf这个目录要替换成你保存防火墙程序的目录
接着,在这个目录下创建两个lua文件,文件名和内容分别是:
cc.lib.lua
function getRealIp()
IP = ngx.var.remote_addr
if ngx.var.HTTP_X_FORWARDED_FOR then --如果用了CDN,判断真实IP
IP = ngx.var.HTTP_X_FORWARDED_FOR
end
if IP == nil then
IP = "unknown"
end
return IP
end
function subString(str, k) --截取字符串
ts = string.reverse(str)
_, i = string.find(ts, k)
m = string.len(ts) - i + 1
return string.sub(str, 1, m)
end
function getClientIp()
IP = ngx.var.remote_addr
if ngx.var.HTTP_X_FORWARDED_FOR then
IP = ngx.var.HTTP_X_FORWARDED_FOR
end
if IP == nil then
IP = "unknown"
end
IP = subString(IP, "[.]") .. "0/24"
return IP
end
function ban_ip(point)
local token = getClientIp() .. "_WAF"
local limit = ngx.shared.limit
local req,_=limit:get(token)
if req then
limit:set(token,req+point,3600) --发现一次,增加积分,1小时内有效
else
limit:set(token,point,3600)
end
end
function get_ban_times()
local token = getClientIp() .. "_WAF"
local limit = ngx.shared.limit
local req,_=limit:get(token)
if req then
return req
else
return 0
end
end
function is_ban()
local ban_times = get_ban_times()
if ban_times >= 100 then --超过100积分,ban
ngx.header.content_type = "text/html;charset=UTF-8"
ngx.status = ngx.HTTP_FORBIDDEN
ngx.say("你访问的太快啦!请等几个小时再来吧")
ngx.exit(ngx.status)
return true
else
return false
end
return false
end
function denycc()
CCcount = 100 --每60秒允许请求100次
CCseconds = 60
local token = getRealIp()
local limit = ngx.shared.limit
local req,_=limit:get(token)
if req then
if req > CCcount then
limit:incr(token,1)
ban_ip(1) --CC攻击,罚分
ngx.header.content_type = "text/html"
ngx.status = ngx.HTTP_FORBIDDEN
ngx.say("请稍安勿躁!慢点访问!")
ngx.exit(ngx.status)
return true
else
limit:incr(token,1)
end
else
limit:set(token,1,CCseconds)
end
return false
end
cc.lua
is_ban()
denycc()
如果你想对一些host不生效,可以:
local hostname = ngx.var.server_name
if hostname ~= "white.example.com" then --不想启用防火墙的host
is_ban()
denycc()
end
保存,重载Nginx,你的防火墙已经生效了