rock-agent是一个全方面管控WAF的守护进程,WAF基于openresty。
在没有server端的情况下,单agent因为无法建立长链,所以并不能直接运行,更加不能执行任何管控功能。
开源完全是为了记录一下之前的学习过程而已。
使用github.com/henrylee2cn/erpc作为tcp通信的框架,更新路由非常方便。
agent启动初会尝试发送安装agent时服务端注册好的agent唯一配置信息,再由服务端决定是否能够建立长链。
后续几乎所有的更新操作都经由这个长链,通过安装下发的agent证书加密通信数据。
服务端在更新新版agent后保存,计算hash,页面点击更新功能后,逻辑分区内的所有agent接收到请求下载agent并在对比hash后重启。
可能的问题是如果上传到服务端的agent本身就没经过测试,跑不起来,那就凉凉了。
agent配置是yaml的,配置变更就是struct转字符串写入文件,然后根据命令决定是否应用配置刷新变量。
代理和转发规则都是nginx作为反代的功能,在openresty里其实可以通过lua来实现;同样各类安全规则,单次请求判断的,比如sqli、xss这种,或者多次请求判断的,比如刷单、爬虫这种(WAF集群中需要一些辅助缓存服务器计数,redis这种;单台WAF就共享内存),也可以在lua中直接实现。
所以本质上规则都是在编译成openresty能执行的字节码后更新到对应业务逻辑集群的lua目录再reload(更新ffi相关的需要restart)。
除此外之前公司大哥改了openresty的源码可以实现部分功能不需要reload直接更新,但是我又忘记了,就不写了。
配置文件内一些变量的set,或者日志路径变更啥的,替换对应位置的字符串再reload。
nginx日志按小时分文件落地,agent起个线程用inotify被动读文件,本地保存文件offset保证断点续传。agent配置的kafka开关决定要不要把读到的日志传到kafka。
当时准备写的一个功能就是峰谷时日志传输,因为业务高峰日志量大,所以会导致网络io大的离谱。
没有在lua里起个异步线程,直接发送日志不落地,是因为不想日志收集这个事影响业务请求处理。没有用logstash这种是因为自己写的比较轻量,没那么占用资源。
定期回传一些agent配置文件内的对应需要收集的信息,cpu,内存啥的,供服务端写简单的规则进行告警。