基于 Nginx 的 WAF 实现

2016-11-08 16:58:15 +08:00
 sophos
作者: Sophos
链接: https://zhuanlan.zhihu.com/p/23447143
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一直以来,陆陆续续有不少同学跟我咨询是否方便公开 Nginx 的 WAF 模块代码。对于这个问题,我个人认为是可以开源的。当然,开源的部分只应包含框架代码, WAF 的规则必须保密。只是从公司的角度来看,这并不属于个人财产,因此我也就不好把这套 WAF 源码分享出来。但又考虑到大家的需求,于是就有了写这篇文章的想法。

先说明一下整个 WAF 系统的结构:

  1. 规则处理模块( nginx )
  2. 日志收集模块( gofluent+httpmq )
  3. 日志分析模块( mysql )
  4. 数据展示模块( web )

规则处理模块

考虑框架的可扩展性,便没有花费过多气力在具体功能的实现上,更多的思考如何使得该框架更为通用。因为后来发现,即便我做再多功夫,一旦某个需求变更,便不得不更改 C 源码,而这又会牵扯到一系列如编译、测试及部署,热更新等问题。

老实说,这套 WAF 模块的代码质量并不算高,毕竟那会儿对于 Nginx 的理解有限。由于这纯属一个人闭门造车,想通过 C 语言实现一个通用的模块框架来 Hack Nginx ,从而提供各种定制 Nginx 功能的方式。但是后来又发现工作量及难度都超出预期,于是只实现了如下功能的框架(或许这就是理想与现实的差距):

日志收集模块

最初我们用的是 fluentd ,期间出了各种问题,最后就用 golang 重写了一套收集与存储的服务。

具体细节可以参考我的这个回答:为什么要使用 Go 语言? Go 语言的优势在哪里? - 知乎用户的回答

日志分析模块及数据展示模块

这个两个部分并不是我负责的,所以技术选型方面我也没有参与。只是做出来的界面不仅难看还难用 (大哭

总结

其实, Nginx 的配置命令就是一种编程语言,没有过多的复杂运算,只是一些简单的赋值。事实上,本身 Nginx 配置是不带有任何语言性质的。类似的正则匹配和逻辑操作都是由其他模块提供的,如 PCRE 库等。

而我所想做的事情,也正是 lua-nginx-module 所实现的。随着之后更加深入的了解,我才知道 Cloudflare 的 WAF 就是基于 lua-nginx-module 实现的。原来他们早就考虑到类似的问题并提出了相应的解决之道。

利用这个 lua-nginx-module 模块,介入到 Nginx 处理 HTTP 请求或相应的各个阶段(如 access , rewrite , content 及 log 等 phase ),首先在请求到对应 location 时,将 Nginx 相关信息记录到 Lua 虚拟机中(或以库的形式提供 Api 给 Lua 调用),再通过 Lua 虚拟机来执行 Nginx 配置中的 Lua 脚本。

后来看了一下 lua-nginx-module 的官方文档,得出以下几点:

若 Lua 仅作为一种独立语言,支持协程可能并不算麻烦。可困难在于 Lua 生来以一门嵌入式语言存在,天生需要大量与宿主系统 C 语言做交互。典型的应用环境是由 C 语言开发的系统,嵌入 Lua 解析器,加载 Lua 脚本运行。同时注入一些 C 函数供 Lua 脚本调用。 Lua 作为控制脚本,并不直接控制外界的模块,做此桥梁的正是那些注入的 C 接口。在较为复杂的应用环境中,这些注入的 C 函数还需要有一些回调方法。当我们企图用 Lua 脚本去定制这些回调行为时,就出现了 C 函数调用 Lua 函数, Lua 函数再调用 C 函数,这个 C 函数又调用 Lua 函数的层层嵌套的过程。

从云风的《 Lua 源码赏析》中看到上面这段文字,使我更为明确了之前的那些猜想。确实, Lua 天生就是与 Nginx 绝配啊。

本来有计划在开发 WAF 2.0 版本的时候,完全通过 lua-nginx-module 来重构的。只是后来跑路了……

(逃

Anyway ,如果现在让我来选型,我这样设计:

  1. 规则处理模块基于 lua-nginx-module
  2. 日志收集模块基于 logstash/rsyslog+kafka
  3. 日志分析模块基于 elasticsearch
  4. 数据展示模块基于 kibana/grafana

仅供参考,欢迎交流。

8414 次点击
所在节点    NGINX
8 条回复
Marser
2016-11-08 17:06:49 +08:00
“ Go 语言的优势在哪里? - 知乎用户的回答 ”没有连接......
daya
2016-11-08 17:13:41 +08:00
@Marser 看不懂,求解释
sophos
2016-11-08 17:18:00 +08:00
@Marser 漏掉了,原文链接里面有。。。
zhangfanfan
2016-11-08 17:18:37 +08:00
看不懂
hcymk2
2016-11-08 17:39:34 +08:00
wwek
2016-11-08 19:01:38 +08:00
期待 op 出官方 waf,在春哥微博问了,他说当然会有
anyforever
2016-11-09 09:29:51 +08:00
@wwek 同期待,这个正是 nginx-lua 的一个很好应用场景
wwek
2016-11-22 08:47:11 +08:00
@anyforever 春哥团队正在新做一个正则引擎,然后利用这个效率最高的正则引擎做 waf

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/319032

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX