几年前,开始在公众视野中不断爆发出应用的安全问题。当时想着应用运维能否也能在nginx中为应用做一层防护,基于该前提下,在Nginx中用Lua做WAF的架构就开始启动。在这里和大家分享一下这套小东西。
整个 WAF 系统的结构
拦截处理模块( nginx 、Lua)
日志收集模块( lua、kafka )
日志分析模块(spark + mysql )
数据展示模块( web )
github中也有ngx_lua_waf开源模块(),但这是静态配置,防护规则配置文件化写死;另一方面,不具有动态分析功能;因此,该模块也属于预想架构中规则处理模块范畴。
整体架构图
拦截处理模块( nginx 、Lua)
为什么选择Lua,而不是nginx C模块开发?主要考虑到一旦某个需求变更,便不得不更改 C 源码,而这又会牵扯到一系列如编译、测试及部署,热更新等问题。
检查部位:header、ua、ip、reffer、request body、uri、uri args。
检查方式:SQL注入、XSS、敏感文件、异常ip、扫描器、XSRF等。
拦截条件需要实时按需改变:利用lua共享内存变量,拦截的时候读取该变量获取拦截条件;同时,nginx配置location,以供调用进行修改拦截条件。
lua_shared_dict rule 5m;
location ~/setrule {
lua {
type : add 增加检查部位或者检查方式
: del 删除检查部位或检查方式
: modify 更新检查部位或者检查方式
}
}
location ~/ {
access_by_lua xxx;//如果用户访问行为符合设置的拦截条件,则进行拒绝访问。
}
通过对setrule接口进行设置,就能动态改变拦截模块中的信息,达到实时效果。
日志收集模块( lua、kafka )
拦截的对象是实时变化,所以,需要收集用户的访问记录,进行动态分析,从而发现可以对象和可以访问行为。
在拦截模块中加入日志收集功能模块就能达到日志流的实时收集,其中需要注意的是,要使用kafka的异步无状态收集方式,这样当应用和kafka中的网络异常和kafka集群挂死的时候,不影响应用的服务。
eg:
local bp = producer:new(broker_list, { producer_type = "async"})
local ok, err = bp:send(queue_name, key, log_content)
if not ok then
ngx.log(ngx.CRIT , err)
return
end
日志分析模块(spark + mysql )
使用spark读取队列中的数据流,用机器学习模型、特征分析、数据统计方法进对日志数据进行分析从而发现可以对象;同时把可以对象进行入库,以供用户在web页面中进行查询。
数据展示模块( web )
构建界面,供用户进行查询。
更多文章请关注,微信订阅号:轻量运维