pull/216/head
midoks 3 years ago
parent 735cf9b872
commit 79a0a93959
  1. 4
      plugins/op_waf/t/index.py
  2. 161
      plugins/op_waf/waf/lua/common.lua
  3. 38
      plugins/op_waf/waf/lua/init.lua
  4. 29
      plugins/op_waf/waf/lua/init_worker.lua

@ -197,14 +197,14 @@ def test_OK():
def test_start(): def test_start():
test_OK() # test_OK()
# test_Dir() # test_Dir()
# test_UA() # test_UA()
# test_POST() # test_POST()
# test_scan() # test_scan()
# test_CC() # test_CC()
# test_url_ext() # test_url_ext()
# test_cdn() test_cdn()
if __name__ == "__main__": if __name__ == "__main__":

@ -6,7 +6,7 @@ local mt = { __index = _M }
local json = require "cjson" local json = require "cjson"
local ngx_match = ngx.re.find local ngx_match = ngx.re.find
local debug_mode = false local debug_mode = true
local waf_root = "{$WAF_ROOT}" local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/" local cpath = waf_root.."/waf/"
@ -23,12 +23,21 @@ function _M.new(self)
config = '', config = '',
site_config = '', site_config = '',
server_name = '', server_name = '',
params = nil global_tatal = nil,
params = nil,
} }
return setmetatable(self, mt) return setmetatable(self, mt)
end end
function _M.getInstance(self)
if rawget(self, "instance") == nil then
rawset(self, "instance", self.new())
end
assert(self.instance ~= nil)
return self.instance
end
function _M.setDebug(self, mode) function _M.setDebug(self, mode)
debug_mode = mode debug_mode = mode
end end
@ -126,11 +135,11 @@ function _M.is_max(self,ip1,ip2)
end end
function _M.split(self, str,reps ) function _M.split(self, str,reps )
local resultStrList = {} local rsList = {}
string.gsub(str,'[^'..reps..']+',function(w) string.gsub(str,'[^'..reps..']+',function(w)
table.insert(resultStrList,w) table.insert(rsList,w)
end) end)
return resultStrList return rsList
end end
function _M.arrip(self, ipstr) function _M.arrip(self, ipstr)
@ -176,13 +185,6 @@ function _M.return_html(self,status,html)
end end
function _M.read_file_body(self, filename) function _M.read_file_body(self, filename)
local key = "file_config_"..filename
local fbody = ngx.shared.waf_limit:get(key, fbody)
if fbody then
return fbody
end
-- self:D("read_file_body:"..filename)
fp = io.open(filename, 'r') fp = io.open(filename, 'r')
if fp == nil then if fp == nil then
return nil return nil
@ -192,37 +194,40 @@ function _M.read_file_body(self, filename)
if fbody == '' then if fbody == '' then
return nil return nil
end end
ngx.shared.waf_limit:set(key,fbody)
return fbody return fbody
end end
function _M.read_file(self, name) function _M.read_file(self, name)
f = self.rpath .. name .. '.json' f = self.rpath .. name .. '.json'
local key = "read_file_"..name
local fbody = ngx.shared.waf_limit:get(key, fbody)
if fbody then
return fbody
end
local fbody = self:read_file_body(f) local fbody = self:read_file_body(f)
if fbody == nil then if fbody == nil then
return {} return {}
end end
local data = json.decode(fbody) local data = json.decode(fbody)
ngx.shared.waf_limit:set(key,data)
return data return data
end end
function _M.read_file_table( self, name )
local key = "read_file_table"..name function _M.select_rule(self, rules)
fbody = ngx.shared.waf_limit:get(key, fbody) if not rules then return {} end
if fbody then new_rules = {}
return fbody for i,v in ipairs(rules)
do
if v[1] == 1 then
table.insert(new_rules,v[2])
end
end end
return new_rules
end
local data = self:select_rule(self:read_file(name)) function _M.read_file_table( self, name )
ngx.shared.waf_limit:set(key,data) return self:select_rule(self:read_file(name))
return data end
function _M.read_file_body_decode(self, name)
return json.decode(self:read_file_body(name))
end end
function _M.write_file(self, filename, body) function _M.write_file(self, filename, body)
@ -236,14 +241,20 @@ function _M.write_file(self, filename, body)
return true return true
end end
function _M.write_file_clear(self, filename, body) function _M.write_file_clear(self, filename, body)
return write_file_clear(filename, body) return write_file_clear(filename, body)
end end
function _M.write_to_file(self, logstr)
local server_name = self.params['server_name']
local filename = self.logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log'
self:write_file(filename, logstr)
return true
end
function _M.write_waf_waf_drop_ip(self, is_drop, drop_time) function _M.write_drop_ip(self, is_drop, drop_time)
local filename = self.logdir .. 'waf_waf_drop_ip.log' local filename = self.logdir .. 'waf_drop_ip.log'
local fp = io.open(filename,'ab') local fp = io.open(filename,'ab')
local server_name = self.params["server_name"] local server_name = self.params["server_name"]
@ -260,13 +271,6 @@ function _M.write_waf_waf_drop_ip(self, is_drop, drop_time)
end end
function _M.write_to_file(self, logstr)
local server_name = self.params['server_name']
local filename = self.logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log'
self:write_file(filename, logstr)
return true
end
function _M.continue_key(self,key) function _M.continue_key(self,key)
key = tostring(key) key = tostring(key)
if string.len(key) > 64 then return false end; if string.len(key) > 64 then return false end;
@ -290,7 +294,7 @@ function _M.array_len(self, arr)
end end
function _M.is_ipaddr(self, client_ip) function _M.is_ipaddr(self, client_ip)
local cipn = self:split_bylog(client_ip,'.') local cipn = self:split(client_ip,'.')
if self:array_len(cipn) < 4 then return false end if self:array_len(cipn) < 4 then return false end
for _,v in ipairs({1,2,3,4}) for _,v in ipairs({1,2,3,4})
do do
@ -301,50 +305,29 @@ function _M.is_ipaddr(self, client_ip)
return true return true
end end
-- 定时异步同步统计信息
function _M.read_file_body_decode(self, name) function _M.timer_stats_total(self)
local key = "read_file_body_decode"..name local total_path = self.cpath .. 'total.json'
local fbody = ngx.shared.waf_limit:get(key, fbody) local total = ngx.shared.waf_limit:get(total_path)
if fbody then if not total then
return fbody
end
local data = json.decode(self:read_file_body(name))
ngx.shared.waf_limit:set(key,data)
return data
end
function _M.select_rule(self, rules)
if not rules then return {} end
new_rules = {}
for i,v in ipairs(rules)
do
if v[1] == 1 then
table.insert(new_rules,v[2])
end
end
return new_rules
end
local function timer_at_inc_log(premature)
local total_path = cpath .. 'total.json'
local tbody = ngx.shared.waf_limit:get(total_path)
if not tbody then
return false return false
end end
return write_file_clear(total_path,tbody) return self:write_file_clear(total_path,total)
end end
function _M.inc_log(self, name, rule) function _M.add_log(self, name, rule)
local server_name = self.params['server_name'] local server_name = self.params['server_name']
local total_path = self.cpath .. 'total.json' local total_path = cpath .. 'total.json'
local tbody = ngx.shared.waf_limit:get(total_path) local total = ngx.shared.waf_limit:get(total_path)
if not tbody then
tbody = self:read_file_body(total_path) if not total then
if not tbody then return false end local tbody = self:read_file_body(total_path)
total = json.decode(tbody)
else
total = json.decode(total)
end end
local total = json.decode(tbody) if not total then return false end
-- 开始计算 -- 开始计算
if not total['sites'] then total['sites'] = {} end if not total['sites'] then total['sites'] = {} end
@ -357,10 +340,7 @@ function _M.inc_log(self, name, rule)
total['sites'][server_name][name] = total['sites'][server_name][name] + 1 total['sites'][server_name][name] = total['sites'][server_name][name] + 1
total['rules'][name] = total['rules'][name] + 1 total['rules'][name] = total['rules'][name] + 1
local total_log = json.encode(total) ngx.shared.waf_limit:set(total_path,json.encode(total))
if not total_log then return false end
ngx.shared.waf_limit:set(total_path,total_log)
-- 异步执行 -- 异步执行
-- 现在改再init_workder.lua 定时执行 -- 现在改再init_workder.lua 定时执行
@ -526,11 +506,11 @@ function _M.write_log(self, name, rule)
local retry_time = config['retry']['retry_time'] local retry_time = config['retry']['retry_time']
local retry_cycle = config['retry']['retry_cycle'] local retry_cycle = config['retry']['retry_cycle']
local count, _ = ngx.shared.waf_waf_drop_ip:get(ip) local count, _ = ngx.shared.waf_drop_ip:get(ip)
if count then if count then
ngx.shared.waf_waf_drop_ip:incr(ip,1) ngx.shared.waf_drop_ip:incr(ip,1)
else else
ngx.shared.waf_waf_drop_ip:set(ip,1,retry_cycle) ngx.shared.waf_drop_ip:set(ip,1,retry_cycle)
end end
if config['log'] ~= true or self:is_site_config('log') ~= true then return false end if config['log'] ~= true or self:is_site_config('log') ~= true then return false end
@ -542,7 +522,7 @@ function _M.write_log(self, name, rule)
local logtmp = {ngx.localtime(), ip, method, ngx.var.request_uri, ngx.var.http_user_agent, name, rule} local logtmp = {ngx.localtime(), ip, method, ngx.var.request_uri, ngx.var.http_user_agent, name, rule}
local logstr = json.encode(logtmp) .. "\n" local logstr = json.encode(logtmp) .. "\n"
local count,_ = ngx.shared.waf_waf_drop_ip:get(ip) local count,_ = ngx.shared.waf_drop_ip:get(ip)
if count > retry and name ~= 'cc' then if count > retry and name ~= 'cc' then
local safe_count,_ = ngx.shared.waf_drop_sum:get(ip) local safe_count,_ = ngx.shared.waf_drop_sum:get(ip)
if not safe_count then if not safe_count then
@ -555,11 +535,11 @@ function _M.write_log(self, name, rule)
if lock_time > 86400 then lock_time = 86400 end if lock_time > 86400 then lock_time = 86400 end
logtmp = {ngx.localtime(),ip,method,ngx.var.request_uri, ngx.var.http_user_agent,name,retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..''} logtmp = {ngx.localtime(),ip,method,ngx.var.request_uri, ngx.var.http_user_agent,name,retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..''}
logstr = logstr .. json.encode(logtmp) .. "\n" logstr = logstr .. json.encode(logtmp) .. "\n"
ngx.shared.waf_waf_drop_ip:set(ip,retry+1,lock_time) ngx.shared.waf_drop_ip:set(ip,retry+1,lock_time)
self:write_waf_waf_drop_ip('inc',lock_time) self:write_drop_ip('inc',lock_time)
end end
self:write_to_file(logstr) self:write_to_file(logstr)
self:inc_log(name,rule) self:add_log(name,rule)
end end
local ffi = require("ffi") local ffi = require("ffi")
@ -640,7 +620,7 @@ function _M.get_real_ip(self, server_name)
if request_header[v] ~= nil and request_header[v] ~= "" then if request_header[v] ~= nil and request_header[v] ~= "" then
local header_tmp = request_header[v] local header_tmp = request_header[v]
if type(header_tmp) == "table" then header_tmp = header_tmp[1] end if type(header_tmp) == "table" then header_tmp = header_tmp[1] end
client_ip = self:split_bylog(header_tmp,',')[1] client_ip = self:split(header_tmp,',')[1]
-- return client_ip -- return client_ip
break; break;
end end
@ -667,11 +647,12 @@ end
function _M.is_site_config(self,cname) function _M.is_site_config(self,cname)
if self.site_config[server_name] ~= nil then local site_config = self.site_config
if site_config[server_name] ~= nil then
if cname == 'cc' then if cname == 'cc' then
return self.site_config[server_name][cname]['open'] return site_config[server_name][cname]['open']
else else
return self.site_config[server_name][cname] return site_config[server_name][cname]
end end
end end
return true return true

@ -2,7 +2,7 @@ local json = require "cjson"
local ngx_match = ngx.re.find local ngx_match = ngx.re.find
local __C = require "common" local __C = require "common"
local C = __C:new() local C = __C:getInstance()
local waf_root = "{$WAF_ROOT}" local waf_root = "{$WAF_ROOT}"
@ -107,7 +107,7 @@ local function save_ip_on(data)
end end
end end
local function remove_waf_waf_waf_drop_ip() local function remove_waf_drop_ip()
if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip') ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
@ -126,22 +126,22 @@ local function remove_waf_waf_waf_drop_ip()
end end
save_ip_on(ip_data2) save_ip_on(ip_data2)
end end
ngx.shared.waf_waf_drop_ip:delete(uri_request_args['ip']) ngx.shared.waf_drop_ip:delete(uri_request_args['ip'])
return get_return_state(true,uri_request_args['ip'] .. '已解封') return get_return_state(true,uri_request_args['ip'] .. '已解封')
end end
local function clean_waf_waf_waf_drop_ip() local function clean_waf_drop_ip()
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip') ret2 = ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data2=json.decode(ret2) ip_data2 = json.decode(ret2)
for k,v in pairs(ip_data2) for k,v in pairs(ip_data2)
do do
v['time']=0 v['time'] = 0
end end
save_ip_on(ip_data2) save_ip_on(ip_data2)
os.execute("sleep " .. 2) os.execute("sleep " .. 2)
end end
local data = get_btwaf_waf_waf_drop_ip() local data = get_waf_drop_ip()
for _,value in ipairs(data) for _,value in ipairs(data)
do do
ngx.shared.waf_waf_drop_ip:delete(value) ngx.shared.waf_waf_drop_ip:delete(value)
@ -151,12 +151,12 @@ end
local function min_route() local function min_route()
if ngx.var.remote_addr ~= '127.0.0.1' then return false end if ngx.var.remote_addr ~= '127.0.0.1' then return false end
if uri == '/get_waf_waf_waf_drop_ip' then if uri == '/get_waf_drop_ip' then
return_message(200,get_waf_waf_waf_drop_ip()) C:return_message(200,get_waf_drop_ip())
elseif uri == '/remove_waf_waf_waf_drop_ip' then elseif uri == '/remove_waf_drop_ip' then
return_message(200,remove_waf_waf_waf_drop_ip()) C:return_message(200,remove_waf_drop_ip())
elseif uri == '/clean_waf_waf_waf_drop_ip' then elseif uri == '/clean_waf_waf_waf_drop_ip' then
return_message(200,clean_waf_waf_waf_drop_ip()) C:return_message(200,clean_waf_drop_ip())
end end
end end
@ -239,17 +239,16 @@ local function waf_cc()
if not config['cc']['open'] or not C:is_site_config('cc') then return false end if not config['cc']['open'] or not C:is_site_config('cc') then return false end
local request_uri = params['request_uri'] local request_uri = params['request_uri']
local endtime = config['cc']['endtime']
local token = ngx.md5(ip .. '_' .. request_uri) local token = ngx.md5(ip .. '_' .. request_uri)
local count = ngx.shared.waf_limit:get(token) local count = ngx.shared.waf_limit:get(token)
local waf_limit = config['cc']['waf_limit'] local endtime = config['cc']['endtime']
local waf_limit = config['cc']['limit']
local cycle = config['cc']['cycle'] local cycle = config['cc']['cycle']
if count then if count then
if count > waf_limit then if count > waf_limit then
local safe_count, _ = ngx.shared.waf_drop_sum:get(ip) local safe_count, _ = ngx.shared.waf_drop_sum:get(ip)
@ -266,7 +265,7 @@ local function waf_cc()
ngx.shared.waf_waf_drop_ip:set(ip,1,lock_time) ngx.shared.waf_waf_drop_ip:set(ip,1,lock_time)
C:write_log('cc',cycle..'秒内累计超过'..waf_limit..'次请求,封锁' .. lock_time .. '') C:write_log('cc',cycle..'秒内累计超过'..waf_limit..'次请求,封锁' .. lock_time .. '')
C:write_waf_waf_drop_ip('cc',lock_time) C:write_drop_ip('cc',lock_time)
ngx.exit(config['cc']['status']) ngx.exit(config['cc']['status'])
return true return true
else else
@ -445,9 +444,8 @@ local function post_data_chekc()
if not aaa then return false end if not aaa then return false end
if tostring(aaa) == 'true' then return false end if tostring(aaa) == 'true' then return false end
if type(aaa) ~= "string" then return false end if type(aaa) ~= "string" then return false end
data_len=split(aaa,list_list) data_len = split(aaa,list_list)
--return return_message(200,data_len)
if not data_len then return false end if not data_len then return false end
if arrlen(data_len) ==0 then return false end if arrlen(data_len) ==0 then return false end

@ -5,39 +5,24 @@ local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/" local cpath = waf_root.."/waf/"
local __C = require "common" local __C = require "common"
local C = __C:new() local C = __C:getInstance()
local function write_file_clear(filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
end
local function timer_at_inc_log(premature) local function timer_stats_log(premature)
local total_path = cpath .. 'total.json' C:timer_stats_total()
local tbody = ngx.shared.waf_waf_limit:get(total_path)
if not tbody then
return false
end
return write_file_clear(total_path, tbody)
end end
ngx.shared.waf_waf_limit:set("cpu_usage", 0, 10) ngx.shared.waf_limit:set("cpu_usage", 0, 10)
function timer_every_get_cpu(premature) function timer_every_get_cpu(premature)
cpu_percent = 80 cpu_percent = 80
ngx.shared.waf_waf_limit:set("cpu_usage", cpu_percent, 10) ngx.shared.waf_limit:set("cpu_usage", cpu_percent, 10)
end end
if 0 == ngx.worker.id() then if 0 == ngx.worker.id() then
ngx.timer.every(5, timer_every_get_cpu) ngx.timer.every(5, timer_every_get_cpu)
-- 异步执行 -- 异步执行
ngx.timer.every(3, timer_at_inc_log) ngx.timer.every(3, timer_stats_log)
end end
Loading…
Cancel
Save