freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

「免费WAF」雷池社区版性能测试
xiao0313 2023-07-21 16:54:02 181553
所属地 浙江省

背景

长亭的社区版 WAF 已经发布有一段时间了。从安全防护能力上讲,长亭差不多是国内 WAF 做的最好的厂商,主打的语义分析技术无论是检测准确性还是误报,都控制得很好。社区版据说也是企业版的检测引擎直接下放,虽然不一定是最新版本,但比其他开源 WAF 还是不知道高到哪里去了。

但社区版的检测性能是否会打折扣呢?以及在我自己站点特定的流量情况下,需要给 WAF 多少资源来保证 WAF 不会被打满了影响业务,这个问题还是需要实测一下的。本文也是尝试通过压测的方法来感受一下雷池社区版的实际性能表现,给大家一些数据供参考,同时也尝试发掘一下社区版雷池是否有可行的性能调优手段,在给定资源的环境下能压榨出更高的检测能力。

测试方案

测试环境

  • CPU:Intel i7-12700

  • 内存:64G DDR5 4800

  • 内核:5.17.15-051715-generic

  • Docker:20.10.21

  • 雷池版本:1.3.0

测试部署

  • WAF:添加一个站点,转发给同样跑在本机的业务服务器
    image

  • 业务服务器:一个 nginx,仅返回最简单的 200 页面
    image

测试工具

wrk:一个简单的 HTTP 性能测试工具

wrk2:魔改的 wrk,可以以固定 QPS 发起测试

测试思路

本次测试主要关注跟流量检测相关的各个服务的性能基准,定义为当为单个服务仅分配且占满一个 CPU 核心时,可以支撑多少 QPS

测试使用两种请求:一是最简单的 GET 请求,没有请求体。二是 GET 请求带请求体,请求体是一个  1K 的 JSON

因为 WAF 性能的核心指标就是每秒可以检测多少个 HTTP 请求,所以 QPS 相对于网络层吞吐而言,是一个更加合理的参数。

测试过程

1. 判断服务的功能

先随意打个 1000 QPS,看看有哪些服务的负载会随 QPS 的变化而变化,用最简单的 GET 请求即可:
image
各个容器的负载情况:
image

由图可见,有三个服务的负载是跟流量相关的:

  • safeline-tengine

  • safeline-detector

  • safeline-mario

从名字可推测,因为 tengine 是阿里 fork 并维护的 nginx 的魔改版,所以这个容器是一个反向代理,用来接收请求并代理给业务服务器;detector 应当是检测服务,nginx 会把请求发送给 detector 做检测,这一点从官方给出的 Nginx 快速集成免费 WAF一文便可知;而 mario 应当是对检测日志做分析和持久化用的,从 detector 和 mario 的配置文件中可见一斑:

  • detector 配置文件
    image

  • mario 配置文件
    image

2. 简单请求测试三个服务的基准性能

先将所有服务的 CPU 使用上限改成 1 核,方法是在 compose.yml 文件里为服务增加 resource limit:
image

然后执行 docker compose up -d 让改动生效(需要在雷池的安装目录下执行,默认是 /data/safeline )
image

然后,我们使用 wrk 看一下能打到多高的 QPS:
image

QPS 打到了 4175
image

从上图可以看到,detector 的 CPU 达到 100%,首先成为瓶颈。

我们来看看 detector 的实际 CPU 占用情况:
image

可以看到 detector 的进程名叫 snserver,是一个多线程的程序,线程数大约等于整机的 CPU 核心数(好像略多几个)。在限定了最高使用一核的情况下, 各个线程都有一点 CPU 占用,但都不高。

这样实际上会导致每个线程每次被唤醒只会跑一小会儿,一堆线程会来回切换,所以 context-switch 的开销会比较高。可以看到 detector 的配置文件里有这么一行配置,应该是在配置线程数,我们把它取消注释并改成 1 来减少 context-switch,试试看 QPS 能否再提升一些。这个文件在安装目录的 resources/detector/snserver.yml 位置,改一下然后重启 detector。
image

线程数减少,说明配置生效了。
image

nginx 也有这个问题,同样把 worker 数降下来
image
wrk 再测一下:
image
QPS 来到了 17000+,这个性能是比较真实的,还不错哦。

但是负载的变化上有个有趣的地方:

A.benchmark 启动之后,detector 与 mario 的负载同时达到 100%。同时这个过程中,可以观察到 mario 的内存在持续上升;
image

B.wrk 结束之后,tengine 与 detector 的负载立刻降回零,但 mario 仍然 100%,注意这个时候 mario 的内存占用超过 2 G;
image

C.又过了一会儿,mario 的 CPU 也降了下来,内存占用也降回 benchmark 前的水位(三百多 MB)
image

于是可以推测:

(1) 对于最简单的 GET 请求,detector 单核可以支撑 17000+ QPS

(2) 但在 17000 QPS 的情况,mario 一个核是不够用的,内存的持续上升推测是日志处理不过来导致队列在快速堆积,这一点从 wrk 停掉之后 mario 仍然在疯狂 100% CPU 也可以得到证明

(3)对于最简单的 GET 请求,mario 的性能是三个服务的瓶颈

由于 GET 请求过于简单,我们就不在这个场景下精确测定每个服务各自跑满单核能够支撑多少 QPS 了,我们直接用复杂请求来测,这样数据更有参考意义。

3. 复杂请求测试三个服务的基准性能

我们用 wrk 的 lua 脚本来生成复杂请求:
image

tcpdump 抓包可以看到发出去的请求是带有 1024 字节 body 的:
image

测得的 QPS 为 10000 出头:
image

各个服务的负载情况:
image

可以看到,detector 不出意外仍然是瓶颈,因为请求变得更大且复杂,检测引擎会消耗更多的 CPU 去检测属于情理之中。

同时,nginx 与 mario 的 CPU 占用均有一些下降。nginx 降低(65% --> 52%)是因为 QPS 的下降会拉低 nginx 的负载、同时请求大小的增加又一定程度上会增加 nginx 的负载,综合起来下降大于上升。而 mario 下降的更多(100% --> 47%),说明 mario 的开销跟 QPS 更敏感,对于请求大小反而不敏感。

从该用例,我们可以得到 detector 单核心的极限 QPS 为 10000

我们再来看下 tengine 的性能,为了让它可以最大限度承压,我们需要给 detector 和 mario 分配更多资源,我们都改成 4 核。
image

nginx 单核心最高可以支撑 28000 QPS,还是很猛的

但 detector 的负载则升到了 326%,相对于之前单核极限的 10000 QPS,似乎多吃了一些 CPU,推测是某种多线程的同步会有额外的开销?
image

继续来测 mario 的单核心极限,因为这个东西超了负载会堆积数据,所以还不能靠单纯的 CPU 限制来测试。一个粗暴的方法是用二分查找来找到一个 QPS,然后利用 wrk2 的固定 QPS 方式来测试,标准为 mario CPU 占用接近 100% 但不出现内存的持续上升

这里的测试结果有些微妙。当我们限定 mario 的 CPU limit 为 1 时,即使只有 10000 QPS,它的内存也很难保证不持续增长。所以只能先放宽这个限制,先分配 2 核心给它。最终测得的一个相对可靠的数字为 11000 QPS 时可以基本保证 CPU 占用为 1 核且内存不会持续上涨。
image

但这个时候有一个更迷惑的点,就是上面测得 detector 单核最高可支撑 10000 QPS,但在 11000 QPS 时 CPU 开销居然到了 247%。这个数字着实有些奇怪。

测试总结

三个关键服务的性能表现如下表所示(请求含有 1K Body):
image

基于此表,我们可以估算一个综合单核 QPS 数,即雷池如果部署在一台只有一个 CPU 核的设备上,大约能承载多少 QPS,可以这样换算:
image.png

一些潜在的优化点:

  1. detector 多线程可能存在一定的锁竞争,导致多核开销偏高

  2. mario 内存占用在高负载时会持续升高,有 OOM 风险

可以看看长亭是否有后续的修复动作,尤其是解决掉上述优化点 2 ,这样后面还可以再测一下一台机器上不限制各服务的资源占用,整体打满之后能打到多高,否则目前测下来可能会炸内存,尤其单机内存相对较小的情况下。

# 网络安全 # web安全 # nginx # WAF产品
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 xiao0313 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
xiao0313 LV.5
这家伙太懒了,还未填写个人描述!
  • 24 文章数
  • 2 关注者
免费WAF雷池入门教学-配置站点HTTP重定向HTTPS
2023-08-24
利用免费WAF雷池社区版解决「爬虫占用网络带宽问题」
2023-08-23
1Panel上的免费WAF长亭雷池搭配openresty的用法
2023-08-21
文章目录