diff --git a/plugins/op_waf/conf/luawaf.conf b/plugins/op_waf/conf/luawaf.conf index 4ac90fd32..140da0509 100755 --- a/plugins/op_waf/conf/luawaf.conf +++ b/plugins/op_waf/conf/luawaf.conf @@ -1,4 +1,8 @@ -lua_shared_dict limit 10m; +lua_shared_dict limit 30m; +lua_shared_dict drop_ip 30m; +lua_shared_dict drop_sum 30m; lua_package_path "{$WAF_PATH}/lua/?.lua"; -init_by_lua_file {$WAF_PATH}/lua/init.lua; -access_by_lua_file {$WAF_PATH}/lua/waf.lua; +access_by_lua_file {$WAF_PATH}/lua/init.lua; + +#init_by_lua_file {$WAF_PATH}/lua/init.lua; +#access_by_lua_file {$WAF_PATH}/lua/waf.lua; diff --git a/plugins/op_waf/waf/domains.json b/plugins/op_waf/waf/domains.json new file mode 100644 index 000000000..13b5173ca --- /dev/null +++ b/plugins/op_waf/waf/domains.json @@ -0,0 +1 @@ +[{"domains": ["www.khxs.org", "khxs.org"], "path": "/www/wwwroot/www.khxs.org", "cms": 0, "name": "www.khxs.org"}, {"domains": ["gae.cachecha.com"], "path": "/www/wwwroot/kkk", "cms": 0, "name": "gae.cachecha.com"}, {"domains": ["ccc.cc"], "path": "/www/wwwroot/ccc.cc", "cms": 0, "name": "ccc.cc"}] \ No newline at end of file diff --git a/plugins/op_waf/waf/lua/common.lua b/plugins/op_waf/waf/lua/common.lua index a170bc0af..55fdf4983 100644 --- a/plugins/op_waf/waf/lua/common.lua +++ b/plugins/op_waf/waf/lua/common.lua @@ -1,6 +1,23 @@ -function return_message(status,msg) +local setmetatable = setmetatable +local _M = { _VERSION = '0.01' } +local mt = { __index = _M } + + +function _M.new(cpath, rpath) + ngx.log(ngx.ERR,"read:"..cpath..",rpath:"..rpath) + local self = { + cpath = cpath, + rpath = rpath, + } + local p = setmetatable(self, mt) + return p +end + + + +function _M.return_message(self, status, msg) ngx.header.content_type = "application/json;" ngx.status = status ngx.say(json.encode(msg)) @@ -8,15 +25,16 @@ function return_message(status,msg) end -function return_html(status,html) +function _M.return_html(self,status,html) ngx.header.content_type = "text/html" ngx.status = status ngx.say(html) ngx.exit(status) end -function read_file_body(filename) - fp = io.open(filename,'r') +function _M.read_file_body(self, filename) + ngx.log(ngx.ERR,"read_file_body:"..filename) + fp = io.open(filename, 'r') if fp == nil then return nil end @@ -28,3 +46,37 @@ function read_file_body(filename) return fbody 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 + + + +function _M.read_file(self, name) + + f = self.rpath .. name .. '.json' + ngx.log(ngx.ERR,"read:"..name) + ngx.log(ngx.ERR,"read2:".. f) + + fbody = self:read_file_body(f) + ngx.log(ngx.ERR,"read3:".. fbody) + if fbody == nil then + return {} + end + return json.decode(fbody) +end + +function _M.t(self) + ngx.say(',,,') +end + + +return _M diff --git a/plugins/op_waf/waf/lua/init.lua b/plugins/op_waf/waf/lua/init.lua index 078e14254..daa9917ab 100644 --- a/plugins/op_waf/waf/lua/init.lua +++ b/plugins/op_waf/waf/lua/init.lua @@ -1,87 +1,138 @@ local cpath = "{$WAF_PATH}/" -local rpath = cpath.."rule/" +local rpath = "{$WAF_PATH}/rule/" local logdir = "{$ROOT_PATH}/wwwlogs/waf/" local json = require "cjson" +local ngx_match = ngx.re.find -function return_message(status,msg) - ngx.header.content_type = "application/json;" - ngx.status = status - ngx.say(json.encode(msg)) - ngx.exit(status) +local _C = require "common" +local C = _C.new(cpath, rpath) + +function read_file(name) + fbody = C:read_file_body(rpath .. name .. '.json') + if fbody == nil then + return {} + end + return json.decode(fbody) end -function return_html(status,html) - ngx.header.content_type = "text/html" - ngx.status = status - ngx.say(html) - ngx.exit(status) +function write_drop_ip(is_drop,drop_time) + local filename = cpath .. 'drop_ip.log' + local fp = io.open(filename,'ab') + if fp == nil then return false end + local logtmp = {os.time(),ip,server_name,request_uri,drop_time,is_drop} + local logstr = json.encode(logtmp) .. "\n" + fp:write(logstr) + fp:flush() + fp:close() + return true end -function return_text(status,html) - ngx.header.content_type = "text/plain" - ngx.status = status - ngx.say(html) - ngx.exit(status) -end +ngx.header.content_type = "text/plain" +-- ngx.say(cpath .. 'config.json') -function read_file_body(filename) - fp = io.open(filename,'r') - if fp == nil then - return nil - end - fbody = fp:read("*a") - fp:close() - if fbody == '' then - return nil + + +local config = json.decode(C:read_file_body(cpath .. 'config.json')) +local site_config = json.decode(C:read_file_body(cpath .. 'site.json')) + + + +function arrlen(arr) + if not arr then return 0 end + count = 0 + for _,v in ipairs(arr) + do + count = count + 1 end - return fbody + return count end - -function read_file(name) - fbody = read_file_body(rpath .. name .. '.json') - if fbody == nil then - return {} +function is_ipaddr(client_ip) + local cipn = split(client_ip,'.') + if arrlen(cipn) < 4 then return false end + for _,v in ipairs({1,2,3,4}) + do + local ipv = tonumber(cipn[v]) + if ipv == nil then return false end + if ipv > 255 or ipv < 0 then return false end end - return json.decode(fbody) + return true end +function get_client_ip() + local client_ip = "unknown" + if site_config[server_name] then + if site_config[server_name]['cdn'] then + for _,v in ipairs(site_config[server_name]['cdn_header']) + do + if request_header[v] ~= nil and request_header[v] ~= "" then + local header_tmp = request_header[v] + if type(header_tmp) == "table" then header_tmp = header_tmp[1] end + client_ip = split(header_tmp,',')[1] + break; + end + end + end + end + if string.match(client_ip,"%d+%.%d+%.%d+%.%d+") == nil or not is_ipaddr(client_ip) then + client_ip = ngx.var.remote_addr + if client_ip == nil then + client_ip = "unknown" + end + end + return client_ip +end -function select_rule(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]) +function get_server_name() + local c_name = ngx.var.server_name + local my_name = ngx.shared.limit:get(c_name) + if my_name then return my_name end + local tmp = C:read_file_body(cpath .. 'domains.json') + if not tmp then return c_name end + local domains = json.decode(tmp) + for _,v in ipairs(domains) + do + for _,d_name in ipairs(v['domains']) + do + if c_name == d_name then + ngx.shared.limit:set(c_name,v['name'],3600) + return v['name'] + end end end - return new_rules + return c_name end +local args_rules = C:select_rule(C:read_file('args')) -local config = json.decode(read_file_body(cpath .. 'config.json')) -local site_config = json.decode(read_file_body(cpath .. 'site.json')) +local retry = config['retry'] +local retry_time = config['retry_time'] +local retry_cycle = config['retry_cycle'] +local ip +local server_name -local args_rules = select_rule(read_file('args')) function continue_key(key) key = tostring(key) if string.len(key) > 64 then return false end; - local keys = {"content","contents","body","msg","file","files","img","newcontent",""} + local keys = {"content","contents","body","msg","file","files","img","newcontent"} for _,k in ipairs(keys) do + ngx.say(k..'---'..key) if k == key then return false end; end + ngx.say('ok:'..key) return true; end 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} @@ -93,10 +144,12 @@ function is_ngx_match(rules,sbody,rule_name) for k,body in pairs(sbody) do - ngx.say('k:'..k..',body:'..body) + 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]) @@ -138,6 +191,17 @@ function is_site_config(cname) 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 @@ -176,9 +240,9 @@ end function inc_log(name,rule) local total_path = cpath .. 'total.json' - local tbody = ngx.shared.btwaf:get(total_path) + local tbody = ngx.shared.limit:get(total_path) if not tbody then - tbody = read_file_body(total_path) + tbody = C:read_file_body(total_path) if not tbody then return false end end local total = json.decode(tbody) @@ -193,10 +257,10 @@ function inc_log(name,rule) total['rules'][name] = total['rules'][name] + 1 local total_log = json.encode(total) if not total_log then return false end - ngx.shared.btwaf:set(total_path,total_log) - if not ngx.shared.btwaf:get('b_btwaf_timeout') then + 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.btwaf:set('b_btwaf_timeout',1,5) + ngx.shared.limit:set('b_btwaf_timeout',1,5) end end @@ -218,15 +282,24 @@ function args() if is_ngx_match(args_rules,uri_request_args,'args') then ngx.say('123123123----4') + ngx.say(get_html) write_log('args','regular') - return_text(config['get']['status'],get_html) + C:return_html(config['get']['status'],get_html) return true end return false end function waf() - args() - return_html(200, json.encode(config)) + + -- server_name = string.gsub(get_server_name(),'_','.') + ngx.header.content_type = "text/plain" + -- ip = get_client_ip() + C:t() + -- ngx.say(read_file('args')); + -- args() + C:return_html(200, '11') -- return_message(200, config) end + +waf()