企业安全建设之使用开源软件建设大规模WAF集群

2018-01-17 18:22:163495人阅读

前言

大多数互联网公司的业务的开展都离不开web服务,web防护也成为众多甲方安全团队需要面对的问题,本文结合实战经验讲述如何使用开源软件搭建大规模WAF集群。为了更有通用性,部分自研模块使用了开源组件代替。自建大型WAF集群开发维护需要相当人力,大家需谨慎,我们经历了2年多才算稳定下来,BAT3和传统4强都有解决方案,大家真可以考虑商业成熟方案。

44_1.jpg

WAF集群架构

44_2.jpg

主要组成为:四层负载均衡、WAF服务、WAF日志处理、WAF配置管理,均支持集群部署,快速横向扩展。

四层负载均衡

从基础网络安全的角度讲,应该严格限制直接使用公网IP对外提供服务的形式,这样攻击面会非常大且不可控。应该所有经过测试的服务才使用负载均衡的方式对外发布WEB服务,其他服务都不直接对外发布,这样可以严格控制黑客的攻击面。四层负载的主要作用是:

四层负载均衡,讲用户请求转发给后端WAF服务

将后端的WAF服务以公网IP的形式发布出去

最好具备一定的抗四层攻击的能力

常见的开源解决方案当属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还有余力。

44_3.jpg

以上图为例,在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服务

常见的开源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写的非常清楚了(https://github.com/loveshell/ngx_lua_waf) ,春哥的也不错(https://github.com/openresty)

我稍微简化了下安装过程:

安装luajit

wget http://luajit.org/download/LuaJIT-2.0.0.tar.gz

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/

安装devel_kit

wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.17rc2.zip

unzip v0.2.17rc2

安装lua-nginx-module

wget https://github.com/chaoslawful/lua-nginx-module/archive/v0.7.4.zip

unzip v0.7.4

安装pcre

wget http://blog.s135.com/soft/linux/nginx_php/pcre/pcre-8.10.tar.gz

tar zxvf pcre-8.10.tar.gz

cd pcre-8.10/

./configure

make && make install

编译nginx

wget 'http://nginx.org/download/nginx-1.2.4.tar.gz'

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

修改nginx配置文件nginx.conf(以下只是原理演示)

http {

include       mime.types;

default_type  application/octet-stream;

#增加以下五行

lua_need_request_body on;

lua_package_path "/usr/local/nginx/conf/waf/?.lua";

lua_shared_dict limit 10m;

init_by_lua_file  /usr/local/nginx/conf/waf/init.lua;

access_by_lua_file /usr/local/nginx/conf/waf/waf.lua;

helloworld规则

[root@instance-vijcg7zo waf]# cat waf.lua

if ngx.var.query_string and ngx.re.match( ngx.var.query_string, "passwd" ) then

-- ngx.say("You are blocked by douge!");

return ngx.exit(ngx.HTTP_FORBIDDEN);

end

[root@instance-vijcg7zo waf]#

访问被拦截

44_4.jpg

配置管理

配置管理其实是整个系统最容易被忽略,但是事实上非常重要的一个环节。

配置同步模型

配置同步最常见的方式有两种:推、拉。推模式实现最方便,但是在大型分布式系统里面无法保证时效性;拉模式性能差。能否兼顾这两种方式呢?

ZK

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

44_5.jpg

核心python伪码为:

#创建zookeeper节点 >>> zookeeper.create(zk,"/zk_waf_rule")

#获取节点信息 >>> zookeeper.get(zk,"/zk_waf_rule")

#定义一个监听器,订阅配置 >>> def myWatch(zk,type,state,path): ...     print "zk:",str(type),str(state),str(path) ...     zookeeper.get(zk,path,myWatch) ... >>> data=zookeeper.get(zk,"/zk_waf_rule",myWatch)

日志处理

44_6.jpg

日志处理也基于流行的storm做实时流式处理,基于spark做离线分析,基于hdfs做离线存储,如果有实时检索原始日志的需求,可以引入es。细节可以参考我之前的文章<企业安全建设之搭建开源SIEM平台(上)>,这部分最基础的功能是:

统计实时拦截报表

统计实时访问PV/UV

离线分析小时/天/周/月的PV/UV

离线分析小时/天/周/月的拦截报表

离线保存原始日志

加分功能是:

跑HMM分析漏报

跑语义分析漏报

总结

生产环境中,远比这个复杂,自研需要谨慎,BAT3以及传统4强的WAF团队人数据说都不是个位数:

nginx层面需要大量优化提高性能

WAF规则需要跟进最新的漏洞,运维量大

开源大数据框架storm、hdfs、spark稳定的运行绝非易事,需要专人维护

nginx+lua架构出于性能考虑单向匹配规则,误报漏报很难取舍。更多优化点请参考我上篇文章<WAF产品经理眼中比较理想的WAF>

本文来自兜哥带你学安全,原文链接:兜哥带你学安全

文章图片来源于网络,如有问题请联系我们

0
现金券
0
兑换券
立即领取
领取成功