Simple Linux Panel
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mdserver-web/plugins/op_waf/waf/lua/init.lua

306 lines
8.8 KiB

6 years ago
local cpath = "{$WAF_PATH}/"
6 years ago
local rpath = "{$WAF_PATH}/rule/"
6 years ago
local logdir = "{$ROOT_PATH}/wwwlogs/waf/"
6 years ago
local json = require "cjson"
6 years ago
local ngx_match = ngx.re.find
6 years ago
6 years ago
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)
6 years ago
end
6 years ago
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
6 years ago
end
6 years ago
6 years ago
ngx.header.content_type = "text/plain"
-- ngx.say(cpath .. 'config.json')
6 years ago
6 years ago
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
6 years ago
end
6 years ago
return count
6 years ago
end
6 years ago
6 years ago
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
6 years ago
end
6 years ago
return true
6 years ago
end
6 years ago
6 years ago
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
6 years ago
6 years ago
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
6 years ago
end
end
6 years ago
return c_name
6 years ago
end
6 years ago
6 years ago
local args_rules = C:select_rule(C:read_file('args'))
6 years ago
6 years ago
local retry = config['retry']
local retry_time = config['retry_time']
local retry_cycle = config['retry_cycle']
local ip
local server_name
6 years ago
6 years ago
function continue_key(key)
key = tostring(key)
if string.len(key) > 64 then return false end;
6 years ago
local keys = {"content","contents","body","msg","file","files","img","newcontent"}
6 years ago
for _,k in ipairs(keys)
do
6 years ago
ngx.say(k..'---'..key)
6 years ago
if k == key then return false end;
end
6 years ago
ngx.say('ok:'..key)
6 years ago
return true;
end
6 years ago
function is_ngx_match(rules,sbody,rule_name)
6 years ago
ngx.say(rules)
6 years ago
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)
6 years ago
do
6 years ago
ngx.say('k:'..k..',body:'..body..tostring(continue_key(k)))
6 years ago
if continue_key(k) then
6 years ago
ngx.say('ddddd-----dddd')
6 years ago
for i,rule in ipairs(rules)
do
6 years ago
ngx.say('i:'..i..',body:'..rule)
6 years ago
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
6 years ago
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
6 years ago
6 years ago
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
6 years ago
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'
6 years ago
local tbody = ngx.shared.limit:get(total_path)
6 years ago
if not tbody then
6 years ago
tbody = C:read_file_body(total_path)
6 years ago
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
6 years ago
ngx.shared.limit:set(total_path,total_log)
if not ngx.shared.limit:get('b_btwaf_timeout') then
6 years ago
write_file(total_path,total_log)
6 years ago
ngx.shared.limit:set('b_btwaf_timeout',1,5)
6 years ago
end
end
function write_to_file(logstr)
6 years ago
local filename = logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log'
6 years ago
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()
6 years ago
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))
6 years ago
if is_ngx_match(args_rules,uri_request_args,'args') then
6 years ago
ngx.say('123123123----4')
6 years ago
ngx.say(get_html)
6 years ago
write_log('args','regular')
6 years ago
C:return_html(config['get']['status'],get_html)
6 years ago
return true
end
return false
end
6 years ago
6 years ago
function waf()
6 years ago
-- 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')
6 years ago
-- return_message(200, config)
6 years ago
end
6 years ago
waf()