官方公众号 企业安全 新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。
对于一种技术的好坏或者方案都需要用辩证思维去看待,不能因为人云亦云就选择去相信,实践是检验真理的唯一标准。
这一篇文章主要讲jxwaf在init阶段所做的行为以及作用
在jxwaf的nginx配置文件里面有两个init阶段:init_by_lua_file和init_worker_by_lua_file
init_by_lua_file /opt/jxwaf/lualib/resty/jxwaf/init.lua; init_worker_by_lua_file /opt/jxwaf/lualib/resty/jxwaf/init_worker.lua;
init_by_lua_file:
在每个nginx worker进程启动时调用指定的lua代码。如果master 进程不允许,则只会在init_by_lua之后调用。这个hook通常用来创建每个工作进程的计时器(定时计划),进行后端健康检查或者重载nginx。
init.lua
resty.core
require "resty.core"
原本openresty是基于lua-nginx-module ,调用 C 函数的 API进行实现,现在新版FFI模式进行处理,lua-resty-core 是把 lua-nginx-module 已有的部分 API,使用 FFI 的模式重新实现了一遍。这样做的好处就是性能处理大大提升,这样说过于抽象,下面使用例子说明, 使用旧版1.13.6.2进行测试,新版默认开启了lua-resty-core ,测试不了 。可以到这里看具体: 为什么你应该在 OpenResty 项目中使用 lua-resty-core
下面代码是没有使用lua-resty-core,循环10亿次进行base64加密,时间是80秒
local start = ngx.now(); for _ =1, 1000000000 do ngx.encode_base64('123456') ngx.update_time(); ngx.say(ngx.now() - start)

require 'resty.core'; local start = ngx.now(); for _ =1, 1000000000 do ngx.encode_base64('123456') ngx.update_time(); ngx.say(ngx.now() - start)

resty.jxwaf.waf
local waf = require "resty.jxwaf.waf" local config_path = "/opt/jxwaf/nginx/conf/jxwaf/jxwaf_config.json" waf.init(config_path)
{ "waf_api_key": "5fc335bc-d778-4d90-ab3f-ece36bad4a24", "waf_api_password": "6bace0ac-ddca-412f-b768-81407044ea0c", "waf_update_website": "http://update2.jxwaf.com/waf_update", "waf_monitor_website": "http://update2.jxwaf.com/waf_monitor", "waf_local":"false", "server_info":"server_info_detail", "waf_node_monitor":"true" }
local _M = {}
local _config_path = "/opt/jxwaf/nginx/conf/jxwaf/jxwaf_config.json"
function _M.init(config_path) local init_config_path = config_path or _config_path local read_config = assert(io.open(init_config_path,'r+')) local raw_config_info = read_config:read('*all') read_config:close() local config_info = cjson.decode(raw_config_info) if config_info == nil then ngx.log(ngx.ERR,"init fail,can not decode config file") if not config_info['waf_node_uuid'] then local waf_node_uuid = uuid.generate_random() config_info['waf_node_uuid'] = waf_node_uuid local new_config_info = cjson.encode(config_info) local write_config = assert(io.open(init_config_path,'w+')) write_config:write(new_config_info) write_config:close() _config_info = config_info iputils.enable_lrucache() local ok, err = process.enable_privileged_agent() if not ok then ngx.log(ngx.ERR, "enables privileged agent failed error:", err) ngx.log(ngx.ALERT,"jxwaf init success,waf node uuid is ".._config_info['waf_node_uuid']) end
return _M
local init_config_path = config_path or _config_path local read_config = assert(io.open(init_config_path,'r+')) local raw_config_info = read_config:read('*all') read_config:close() local config_info = cjson.decode(raw_config_info) if config_info == nil then ngx.log(ngx.ERR,"init fail,can not decode config file") end

if not config_info['waf_node_uuid'] then local waf_node_uuid = uuid.generate_random() config_info['waf_node_uuid'] = waf_node_uuid local new_config_info = cjson.encode(config_info) local write_config = assert(io.open(init_config_path,'w+')) write_config:write(new_config_info) write_config:close()
iputils.enable_lrucache()
init_by_lua_block { local iputils = require("resty.iputils") iputils.enable_lrucache() --创建全局缓存空间 local whitelist_ips = { "127.0.0.1", "10.10.10.0/24", --白名单地址 -- WARNING: Global variable, recommend this is cached at the module level -- https://github.com/openresty/lua-nginx-module#data-sharing-within-an-nginx-worker whitelist = iputils.parse_cidrs(whitelist_ips) --取得CIDR格式IPV4网络表,并返回包含低地址和高地址的表的表。 access_by_lua_block { local iputils = require("resty.iputils") if not iputils.ip_in_cidrs(ngx.var.remote_addr, whitelist) then --如果不在IP白名单内,返回403状态码 return ngx.exit(ngx.HTTP_FORBIDDEN) }

local ok, err = process.enable_privileged_agent() if not ok then ngx.log(ngx.ERR, "enables privileged agent failed error:", err) ngx.log(ngx.ALERT,"jxwaf init success,waf node uuid is ".._config_info['waf_node_uuid'])
local waf = require "resty.jxwaf.waf" waf.init_worker()
init_worker.lua
function _M.init_worker() if _config_info.waf_local == "false" then if process.type() == "privileged agent" then if _config_info.waf_node_monitor == "true" then local monitor_ok,monitor_err = ngx.timer.at(0,_momitor_update) if not monitor_ok then if monitor_err ~= "process exiting" then ngx.log(ngx.ERR, "failed to create the init timer: ", init_err) local init_ok,init_err = ngx.timer.at(0,_global_update_rule) if not init_ok then if init_err ~= "process exiting" then ngx.log(ngx.ERR, "failed to create the init timer: ", init_err) local worker_init_ok,worker_init_err = ngx.timer.at(0,_worker_update_rule) if not worker_init_ok then if worker_init_err ~= "process exiting" then ngx.log(ngx.ERR, "failed to create the init timer: ", worker_init_err) local hdl, err = ngx.timer.every(5,_worker_update_rule) if err then ngx.log(ngx.ERR, "failed to create the worker update timer: ", err) end

--local ok, err = process.enable_privileged_agent() --if not ok then -- ngx.log(ngx.ERR, "enables privileged agent failed error:", err) --end

特权代理
if _config_info.waf_node_monitor == "true" then
local monitor_ok,monitor_err = ngx.timer.at(0,_momitor_update)
if not monitor_ok then
if monitor_err ~= "process exiting" then
ngx.log(ngx.ERR, "failed to create the init timer: ", init_err)
end
end
end
local init_ok,init_err = ngx.timer.at(0,_global_update_rule)
if not init_ok then
if init_err ~= "process exiting" then
ngx.log(ngx.ERR, "failed to create the init timer: ", init_err)
end
end
local function _momitor_update() local _update_website = _config_info.waf_monitor_website or "https://update2.jxwaf.com/waf_monitor" local httpc = http.new() httpc:set_timeouts(5000, 5000, 30000) local api_key = _config_info.waf_api_key or "" local api_password = _config_info.waf_api_password or "" local server_info = _config_info.server_info or "" local waf_node_uuid = _config_info.waf_node_uuid or "" local res, err = httpc:request_uri( _update_website , { method = "POST", body = "api_key="..api_key.."&api_password="..api_password.."&waf_node_uuid="..waf_node_uuid.."&server_info="..server_info, headers = { ["Content-Type"] = "application/x-www-form-urlencoded", if not res then ngx.log(ngx.ERR,"failed to request: ", err) return _update_at(tonumber(_auto_update_period),_momitor_update) local res_body = cjson.decode(res.body) if not res_body then ngx.log(ngx.ERR,"init fail,failed to decode resp body " ) return _update_at(tonumber(_auto_update_period),_momitor_update) if res_body['result'] == false then ngx.log(ngx.ERR,"init fail,failed to request, ",res_body['message']) return _update_at(tonumber(_auto_update_period),_momitor_update) _waf_node_monitor = res_body['waf_node_monitor'] or _waf_node_monitor if _waf_node_monitor == "true" then local global_ok, global_err = ngx.timer.at(tonumber(_waf_node_monitor_period),_momitor_update) if not global_ok then if global_err ~= "process exiting" then ngx.log(ngx.ERR, "failed to create the cycle timer: ", global_err) ngx.log(ngx.ALERT,"monitor report success") end







if not res_body['no_update'] then
local tmp_waf_rule = res_body['waf_rule'] if tmp_waf_rule == nil then ngx.log(ngx.ERR,"init fail,can not decode waf rule") return _update_at(tonumber(_auto_update_period),_global_update_rule) _update_waf_rule = tmp_waf_rule --将规则内容赋值到这个变量 if _update_waf_rule == nil then ngx.log(ngx.ERR,"init fail,can not decode waf rule") return _update_at(tonumber(_auto_update_period),_global_update_rule) end



local table_sort = table.sort local function _sort_rules(a,b) if a.rule_level == b.rule_level then return tonumber(a.rule_id)<tonumber(b.rule_id) return tonumber(a.rule_level)>tonumber(b.rule_level) for k,v in pairs(_update_waf_rule) do if type(v['custom_rule_set']) == "table" then table_sort(v['custom_rule_set'],_sort_rules) _update_waf_rule[k] = v end


if res_body['botcheck'] then local load_botcheck = loadstring(ngx.decode_base64(res_body['botcheck']))() if load_botcheck then _bot_check = load_botcheck end
if res_body['bot_auth_key'] then local bot_check_info = res_body['bot_auth_key'] bot_check_standard_info = bot_check_info['standard'] bot_check_image_info = bot_check_info['image'] bot_check_slipper_info = bot_check_info['slipper'] local standard_key = {} local slipper_key = {} local image_key = {} for k,_ in pairs(bot_check_standard_info) do table.insert(standard_key,k) bot_check_standard_key = standard_key for k,_ in pairs(bot_check_slipper_info) do table.insert(slipper_key,k) bot_check_slipper_key = slipper_key for k,_ in pairs(bot_check_image_info) do table.insert(image_key,k) bot_check_image_key = image_key ngx.log(ngx.ERR, "bot check standard key count is ",#bot_check_standard_key) ngx.log(ngx.ERR, "bot check key image count is ",#bot_check_slipper_key) ngx.log(ngx.ERR, "bot check key slipper count is ",#bot_check_image_key) end


if res_body['log_conf'] then _log_conf = res_body['log_conf'] end
"log_conf": {"log_port": "5555", "all_request_log": "false", "log_local": "true", "log_ip": "127.0.0.1", "log_remote": "false"}
local waf_common_conf = ngx.shared.waf_common_conf local md5_succ, md5_err = waf_common_conf:set("md5",res_body['md5']) if md5_err then ngx.log(ngx.ERR,"init fail,can not set waf_common_conf md5") return _update_at(tonumber(_auto_update_period),_global_update_rule) local res_body_succ, res_body_err = waf_common_conf:set("res_body",res.body) if res_body_err then ngx.log(ngx.ERR,"init fail,can not set waf_common_conf res_body") return _update_at(tonumber(_auto_update_period),_global_update_rule) _md5 = res_body['md5'] ngx.log(ngx.ALERT,"global config info md5 is ".._md5..",update config info success")
worker


- 0 文章数
- 0 评论数
- 0 关注者
请 登录 / 注册 后在FreeBuf发布内容哦