从去年到现在,在公司一共经历了两个基于NIDS的项目,我负责在NIDS系统之上进行开发安全检测系统。在两个项目中我的工作基本类似,获取结构化的网络流量数据,然后基于一定的算法规则检测网络中是否存在攻击或者异常行为。
两个项目虽然虽然不同,但是都基于流量采集,也都是把采集的流量存放在elasticsearch当中,也正是因为这一设计,导致之后我们遇到的无穷的问题。
问题
在类似的NIDS中,流量采集一般都是由C语言编写,常见的框架有libpcap、pfring、dpdk等,对CPU消耗很大,不宜在此阶段执行业务逻辑。
因此许多项目都是把解析之后的流量数据发送到elasticsearch等数据仓库就不管了,其后所有分析都从elasticsearch拉取数据进行。这是问题的原罪设计。
es作为所有检测的源数据提供方,查询压力非常大,在数据量很大(>10e条)的情况,会不受控制的吃完系统所有内存,导致系统可用内存不足,从而整个系统陷入不可用的状态。
示意图如下:
解决思路
多数人看到这种情况,会觉得主要问题是es吃内存太多,想当然的提出替换es存储的解决方案。然而此方案并不可行,无论何种存储系统,在占用内存、存储数据规模、查询响应速度三个方面都存在根本的矛盾。这里es是单一存储,存储了海量数据,且需要提供给各种业务方秒级甚至毫秒级的查询,换了一个组件,可能占用内存下去了,但是响应速度会变得不可接受,又或者内存、查询响应的指标ok了,但并不适合存储海量数据。
即便出现了一个所有指标十倍优于es的存储组件,那么当数据规模达到100e时,相同的问题仍然会发生。
因此我们需要换一个角度思考,即减轻es的压力。
这个时候我们需要从业务的角度拆解数据流。哪些业务可能需要多次查询数据,哪些业务只是需要遍历一次网络流量?
根据这个原则,多数实时检测的业务不应当直接查询es,仅用户需要查询流量细节的时候才需要查询es。
此时es的定位就是一个查询不频繁(多数查询由用户发起的)的数据仓库,大部分数据应当处于冷的状态(此时的es不消耗内存)。
最终示意图如下: