diff --git a/plugins/op_waf/waf/lua/common.lua b/plugins/op_waf/waf/lua/common.lua index d831df170..23197b8cd 100644 --- a/plugins/op_waf/waf/lua/common.lua +++ b/plugins/op_waf/waf/lua/common.lua @@ -4,13 +4,15 @@ local setmetatable = setmetatable local _M = { _VERSION = '0.01' } local mt = { __index = _M } local json = require "cjson" +local ngx_match = ngx.re.find -function _M.new(cpath, rpath) +function _M.new(cpath, rpath, logdir) -- ngx.log(ngx.ERR,"read:"..cpath..",rpath:"..rpath) local self = { cpath = cpath, rpath = rpath, + logdir = logdir, config = '', site_config = '' } @@ -55,6 +57,26 @@ function _M.read_file_body(self, filename) return fbody end + + +function _M.write_file(self, filename, body) + fp = io.open(filename,'w') + if fp == nil then + return nil + end + fp:write(body) + fp:flush() + fp:close() + return true +end + + +function _M.write_to_file(logstr) + local filename = self.logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log' + self:write_file(filename, logstr) + return true +end + function _M.continue_key(self,key) key = tostring(key) if string.len(key) > 64 then return false end; @@ -122,6 +144,33 @@ function _M.read_file_table( self, name ) end +function _M.inc_log(self, name, rule) + local total_path = cpath .. 'total.json' + local tbody = ngx.shared.limit:get(total_path) + if not tbody then + tbody = self:read_file_body(total_path) + if not tbody then return false end + end + local total = json.decode(tbody) + if not total['sites'] then total['sites'] = {} end + if not total['sites'][server_name] then total['sites'][server_name] = {} end + if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end + if not total['rules'] then total['rules'] = {} end + if not total['rules'][name] then total['rules'][name] = 0 end + if not total['total'] then total['total'] = 0 end + total['total'] = total['total'] + 1 + total['sites'][server_name][name] = total['sites'][server_name][name] + 1 + total['rules'][name] = total['rules'][name] + 1 + local total_log = json.encode(total) + if not total_log then return false end + ngx.shared.limit:set(total_path,total_log) + if not ngx.shared.limit:get('b_btwaf_timeout') then + self:write_file(total_path,total_log) + ngx.shared.limit:set('b_btwaf_timeout',1,5) + end +end + + --------------------------------------------------- function _M.get_server_name(self) @@ -145,6 +194,103 @@ function _M.get_server_name(self) end +-- function _M.get_sn(self) +-- retun string.gsub(self:get_server_name(),'_','.') +-- end + + +function _M.is_ngx_match(self, rules, sbody, rule_name) + ngx.say() + if rules == nil or sbody == nil then return false end + if type(sbody) == "string" then + sbody = {sbody} + end + + if type(rules) == "string" then + rules = {rules} + end + + for k,body in pairs(sbody) + do + if self:continue_key(k) then + for i,rule in ipairs(rules) + do + ngx.say("i:"..i..",rule:"..rule) + if self.site_config[server_name] and rule_name then + local n = i - 1 + for _,j in ipairs(self.site_config[server_name]['disable_rule'][rule_name]) + do + if n == j then + rule = "" + end + end + end + + if body and rule ~="" then + if type(body) == "string" then + if ngx_match(ngx.unescape_uri(body),rule,"isjo") then + error_rule = rule .. ' >> ' .. k .. ':' .. body + return true + end + end + if type(k) == "string" then + if ngx_match(ngx.unescape_uri(k),rule,"isjo") then + error_rule = rule .. ' >> ' .. k + return true + end + end + end + end + end + end + return false +end + + +function _M.write_log(self, name, rule) + ngx.say('name:'..name) + local ip = C:get_client_ip() + + + + local count,_ = ngx.shared.drop_ip:get(ip) + if count then + ngx.shared.drop_ip:incr(ip,1) + else + ngx.shared.drop_ip:set(ip,1,retry_cycle) + end + if self.config['log'] ~= true or self:is_site_config('log') ~= true then return false end + local method = ngx.req.get_method() + if error_rule then + rule = error_rule + error_rule = nil + end + + + local logtmp = {ngx.localtime(), ip, method,request_uri, ngx.var.http_user_agent, name, rule} + ngx.say('logtmp:'..logtmp) + local logstr = json.encode(logtmp) .. "\n" + local count,_ = ngx.shared.drop_ip:get(ip) + if count > retry and name ~= 'cc' then + local safe_count,_ = ngx.shared.drop_sum:get(ip) + if not safe_count then + ngx.shared.drop_sum:set(ip,1,86400) + safe_count = 1 + else + ngx.shared.drop_sum:incr(ip,1) + end + local lock_time = retry_time * safe_count + if lock_time > 86400 then lock_time = 86400 end + logtmp = {ngx.localtime(),ip,method,request_uri,ngx.var.http_user_agent,name,retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..'秒'} + logstr = logstr .. json.encode(logtmp) .. "\n" + ngx.shared.drop_ip:set(ip,retry+1,lock_time) + self:write_drop_ip('inc',lock_time) + end + self:write_to_file(logstr) + self:inc_log(name,rule) +end + + function _M.get_client_ip(self) local client_ip = "unknown" if self.site_config[server_name] then @@ -169,6 +315,19 @@ function _M.get_client_ip(self) return client_ip end + +function _M.is_site_config(self,cname) + if self.site_config[server_name] ~= nil then + if cname == 'cc' then + return self.site_config[server_name][cname]['open'] + else + return self.site_config[server_name][cname] + end + end + return true +end + + function _M.t(self) ngx.say(',,,') end diff --git a/plugins/op_waf/waf/lua/init.lua b/plugins/op_waf/waf/lua/init.lua index 1db603c33..6550b8fd5 100644 --- a/plugins/op_waf/waf/lua/init.lua +++ b/plugins/op_waf/waf/lua/init.lua @@ -6,7 +6,7 @@ local json = require "cjson" local ngx_match = ngx.re.find local _C = require "common" -local C = _C.new(cpath, rpath) +local C = _C.new(cpath, rpath, logdir) function write_drop_ip(is_drop,drop_time) @@ -22,7 +22,7 @@ function write_drop_ip(is_drop,drop_time) end -ngx.header.content_type = "text/plain" + local config = C:read_file_body_decode(cpath .. 'config.json') local site_config = C:read_file_body_decode(cpath .. 'site.json') @@ -30,10 +30,6 @@ local site_config = C:read_file_body_decode(cpath .. 'site.json') C.setConfData(config, site_config) - - - - local args_rules = C:read_file_table('args') local retry = config['retry'] @@ -44,161 +40,12 @@ local server_name = string.gsub(C:get_server_name(),'_','.') - -function is_ngx_match(rules,sbody,rule_name) - - ngx.say(rules) - if rules == nil or sbody == nil then return false end - if type(sbody) == "string" then - sbody = {sbody} - end - - if type(rules) == "string" then - rules = {rules} - end - - for k,body in pairs(sbody) - do - ngx.say('k:'..k..',body:'..body..tostring(continue_key(k))) - if continue_key(k) then - ngx.say('ddddd-----dddd') - for i,rule in ipairs(rules) - do - ngx.say('i:'..i..',body:'..rule) - if site_config[server_name] and rule_name then - local n = i - 1 - for _,j in ipairs(site_config[server_name]['disable_rule'][rule_name]) - do - if n == j then - rule = "" - end - end - end - - if body and rule ~="" then - if type(body) == "string" then - if ngx_match(ngx.unescape_uri(body),rule,"isjo") then - error_rule = rule .. ' >> ' .. k .. ':' .. body - return true - end - end - if type(k) == "string" then - if ngx_match(ngx.unescape_uri(k),rule,"isjo") then - error_rule = rule .. ' >> ' .. k - return true - end - end - end - end - end - end - return false -end - -function is_site_config(cname) - if site_config[server_name] ~= nil then - if cname == 'cc' then - return site_config[server_name][cname]['open'] - else - return site_config[server_name][cname] - end - end - return true -end - -function write_file(filename,body) - fp = io.open(filename,'w') - if fp == nil then - return nil - end - fp:write(body) - fp:flush() - fp:close() - return true -end - -function write_log(name,rule) - local count,_ = ngx.shared.drop_ip:get(ip) - if count then - ngx.shared.drop_ip:incr(ip,1) - else - ngx.shared.drop_ip:set(ip,1,retry_cycle) - end - if config['log'] ~= true or is_site_config('log') ~= true then return false end - local method = ngx.req.get_method() - if error_rule then - rule = error_rule - error_rule = nil - end - - local logtmp = {ngx.localtime(),ip,method,request_uri,ngx.var.http_user_agent,name,rule} - local logstr = json.encode(logtmp) .. "\n" - local count,_ = ngx.shared.drop_ip:get(ip) - if count > retry and name ~= 'cc' then - local safe_count,_ = ngx.shared.drop_sum:get(ip) - if not safe_count then - ngx.shared.drop_sum:set(ip,1,86400) - safe_count = 1 - else - ngx.shared.drop_sum:incr(ip,1) - end - local lock_time = retry_time * safe_count - if lock_time > 86400 then lock_time = 86400 end - logtmp = {ngx.localtime(),ip,method,request_uri,ngx.var.http_user_agent,name,retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..'秒'} - logstr = logstr .. json.encode(logtmp) .. "\n" - ngx.shared.drop_ip:set(ip,retry+1,lock_time) - write_drop_ip('inc',lock_time) - end - write_to_file(logstr) - inc_log(name,rule) -end - -function inc_log(name,rule) - local total_path = cpath .. 'total.json' - local tbody = ngx.shared.limit:get(total_path) - if not tbody then - tbody = C:read_file_body(total_path) - if not tbody then return false end - end - local total = json.decode(tbody) - if not total['sites'] then total['sites'] = {} end - if not total['sites'][server_name] then total['sites'][server_name] = {} end - if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end - if not total['rules'] then total['rules'] = {} end - if not total['rules'][name] then total['rules'][name] = 0 end - if not total['total'] then total['total'] = 0 end - total['total'] = total['total'] + 1 - total['sites'][server_name][name] = total['sites'][server_name][name] + 1 - total['rules'][name] = total['rules'][name] + 1 - local total_log = json.encode(total) - if not total_log then return false end - ngx.shared.limit:set(total_path,total_log) - if not ngx.shared.limit:get('b_btwaf_timeout') then - write_file(total_path,total_log) - ngx.shared.limit:set('b_btwaf_timeout',1,5) - end -end - -function write_to_file(logstr) - local filename = logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log' - local fp = io.open(filename,'ab') - if fp == nil then return false end - fp:write(logstr) - fp:flush() - fp:close() - return true -end - -function args() +function waf_args() uri_request_args = ngx.req.get_uri_args() - ngx.say('123123123----111') - if not config['get']['open'] or not is_site_config('get') then return false end - ngx.say('123123123----22'..json.encode(uri_request_args)) - - if is_ngx_match(args_rules,uri_request_args,'args') then - ngx.say('123123123----4') - ngx.say(get_html) - write_log('args','regular') + if not config['get']['open'] or not C:is_site_config('get') then return false end + if C:is_ngx_match(args_rules,uri_request_args,'args') then + ngx.say('okkkkkooo') + C:write_log(ip,'args','regular') C:return_html(config['get']['status'],get_html) return true end @@ -206,12 +53,8 @@ function args() end function waf() - - -- server_name = string.gsub(get_server_name(),'_','.') ngx.header.content_type = "text/plain" - C:t() - -- ngx.say(read_file('args')); - -- args() + waf_args() C:return_html(200, '11') -- return_message(200, config) end