本文暨 FreeBuf 公开课课后总结,回顾公开课实况请点我
大多数互联网公司的业务的开展都离不开 web 服务,web 防护也成为众多甲方安全团队需要面对的问题,本文结合实战经验讲述如何使用开源软件搭建大规模 WAF 集群。为了更有通用性,部分自研模块使用了开源组件代替。自建大型 WAF 集群开发维护需要相当人力,大家需谨慎,BAT3 和传统 4 强都有解决方案,大家真可以考虑商业成熟方案。
主要组成为:四层负载均衡、WAF 服务、WAF 日志处理、WAF 配置管理,均支持集群部署,快速横向扩展。
从基础网络安全的角度讲,应该严格限制直接使用公网 IP 对外提供服务的形式,这样攻击面会非常大且不可控。应该所有经过测试的服务才使用负载均衡的方式对外发布 WEB 服务,其他服务都不直接对外发布,这样可以严格控制黑客的攻击面。四层负载的主要作用是:
常见的开源解决方案当属 LVS。LVS 是 Linux Virtual Server 的简写,意即 Linux 虚拟服务器,是一个虚拟的服务器集群系统,支持 VS-NAT 、 VS-TUN 、 VS-DR 三种模式:
VS-NAT:就是把客户端发来的数据包的 IP 头的目的地址,在负载均衡器上换成其中一台 RS 的 IP 地址,并发至此 RS 来处理, RS 处理完成后把数据交给经过负载均衡器, 负载均衡器再把数据包的原 IP 地址改为自己的 IP,将目的地址改为客户端 IP 地址即可。期间, 无论是进来的流量, 还是出去的流量, 都必须经过负载均衡器。
VS-TUN:把客户端发来的数据包,封装一个新的 IP 头标记 (仅目的 IP) 发给 RS,RS 收到后, 先把数据包的头解开, 还原数据包, 处理后, 直接返回给客户端, 不需要再经过负载均衡器。注意, 由于 RS 需要对负载均衡器发过来的数据包进行还原, 所以说必须支持 IPTUNNEL 协议。所以, 在 RS 的内核中, 必须编译支持 IPTUNNEL 这个选项。
VS-DR:负载均衡器和 RS 都使用同一个 IP 对外服务,由于负载均衡器要对二层包头进行改换, 所以负载均衡器和 RS 之间必须在一个广播域, 也可以简单的理解为在同一台交换机上。
由于我们希望仅 LVS 暴露在公网,后端 WAF 和 WEB 服务的部署不要有太多物理机柜网段限制,推荐使用 VS-NAT 模式,虽然全部请求和应答都会过 LVS,LVS 可能会成为整个系统的瓶颈,但是实际经验是 LVS 性能足够好,单机性能瓶颈往往是网卡,万兆网卡打满的情况下 CPU 还有余力。
以上图为例,在 LVS 上配置如下:
- /sbin/ipvsadm -C
- /sbin/ipvsadm -a -t 201.114.5.36:80 -r 192.168.1.100:80 -m -w 1
- /sbin/ipvsadm -a -t 201.114.5.36:80 -r 192.168.1.101:80 -m -w 1
- /sbin/ipvsadm
注:两台 LVS 之间可以起 vrrp 虚拟出 VIP 起到高可用的效果,更多生产环境的优化请自行补充。
常见的开源 WAF 有 mod_security 和 nginx+lua,由于 nginx 卓越的性能以及 lua 的编程级灵活性,nginx+lua 成为了更多人的选择,一个代码示例如下:
- location /
- {
- default_type 'text/plain';
- access_by_lua '
- local waf = require "waf" ;
- waf.execute() ';
- }
其中 所有真实的 WAF 工作被用 lua 写的 waf 模块做了。这部分在 loveshell 写的非常清楚 了 ( ) ,春哥的也不错( )
我稍微简化了下安装过程:
wget
tar zxvf LuaJIT-2.0.0.tar.gz
cd LuaJIT-2.0.0
make
make install PREFIX=/usr/local/lj2
ln -s /usr/local/lj2/lib/libluajit-5.1.so.2 /lib64/
wget
unzip v0.2.17rc2
wget
unzip v0.7.4
wget
tar zxvf pcre-8.10.tar.gz
cd pcre-8.10/
./configure
make && make install
wget ' '
tar -xzvf nginx-1.2.4.tar.gz
cd nginx-1.2.4/
export LUAJIT_LIB=/usr/local/lj2/lib/
export LUAJIT_INC=/usr/local/lj2/include/luajit-2.0/
./configure --user=daemon --group=daemon --prefix=/usr/local/nginx/ --with-http_stub_status_module --with-http_sub_module --with-http_gzip_static_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --add-module=../ngx_devel_kit-0.2.17rc2/ --add-module=../lua-nginx-module-0.7.4/
make -j8
make install
配置管理其实是整个系统最容易被忽略,但是事实上非常重要的一个环节。
配置同步最常见的方式有两种:推、拉。推模式实现最方便,但是在大型分布式系统里面无法保证时效性;拉模式性能差。能否兼顾这两种方式呢?
ZooKeeper 是一个分布式协调服 务 ,是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper 在分布式系统的配置管理方面应用非常广泛。ZooKeeper 支持发布订阅模式,该模式可以看成一对多的关系:多个订阅者对象同时监听一个主题对象,这个主题对象在自身状态发生变化时,会通知所有的订阅者对象,使他们能够自动的更新自己的状态。发布订阅模式,可以让发布方和订阅方,独立封装,独立改变,当一个对象的改变,需要同时改变其他的对象,而且它不知道有多少个对象需要改变时,可以使用发布订阅模式。
在最简化设计时,我们可以让每台 WAF 的配置完全一样,这样的好处是可以随时添加服务器,任何一个服务器宕机都不会影响 WAF 服务,而且整个系统的架构会非常简洁。每台 WAF 只要使用 python 脚本订阅 ZK 中的配置,一旦发生变更,获取最新配置,更新相关配置文件,给 nginx 发送信号热加载新配置文件即可( nginx -s reload)。
ZK 的安装使用非常简单
下载,解压就 ok 了。
编辑配置文件 conf/zoo.cfg
- tickTime=2000
- dataDir=/var/lib/zookeeper
- clientPort=2181
启动服务
- bin/zkServer.sh start
建议至少使用三个 zk 实例,而且分布在不同服务器上,可以和 WAF 混合部署,因为对性能消耗很小。
- tickTime=2000
- dataDir=/var/lib/zookeeper
- clientPort=2181
- initLimit=5
- syncLimit=2
- server.1=zoo1:2888:3888
- server.2=zoo2:2888:3888
- server.3=zoo3:2888:3888
核心 python 伪码为:
日志处理
日志处理也基于流行的 storm 做实时流式处理,基于 spark 做离线分析,基于 hdfs 做离线存储,如果有实时检索原始日志的需求,可以引入 es。细节可以参考我之前的文章 <企业安全建设之搭建开源 SIEM 平台(上)>, 这部分最基础的功能是:
生产环境中,远比这个复杂,自研需要谨慎,BAT3 以及传统 4 强的 WAF 团队人数据说都不是个位数:
来源: http://www.tuicool.com/articles/ryqMRnE