基于Flink构建关联分析引擎Sabre的挑战和实践随着云计算、大数据等新一代IT技术在各行业的深入应用,政企机构IT规模和复杂程度不断提高,网络流量、日志等各类数据规模大幅提升。与此同时,网络攻防日益激烈,网络安全威胁逐渐凸显出来,这对于SOC/SIEM产品的性能提出了一个很大的挑战。因此,奇安信独立研发了国内首款流式分布式关联分析引擎Sabre,搭载于公司旗下态势感知与安全运营平台(下文简称NGSOC),从而大幅提升NGSOC的数据分析能力和网络安全检测能力。本文将从技术研发的角度,全面阐述Sabre的由来。1.Sabre是什么?Sabre是奇安信研发的新一代流式分布式关联分析引擎,是CEP(ComplexEventProcessing,复杂事件处理)技术在大数据领域的一个具体实现。奇安信研发关联引擎已有数年历史,中间经历了三次主要的技术演进,在2015年之前,奇安信使用的是基于开源CEP软件Esper研发的关联引擎,由于一些架构和设计上的问题,整体性能不是非常理想,也不支持多机扩展;在2016-2017年,用C++开发了一个高性能引擎,代号Dolphin,可以在单机上实现很高的性能;在2018年,从技术上全面转向Flink框架,极大增强了系统的可扩展性,推出了Sabre引擎作为NGSOC的核心检测引擎。Sabre应用于奇安信的态势感知与安全运营平台(NGSOC)产品中,NGSOC主要服务于中大型政企客户,目前已经成功应用于200+大型政企机构,在国内安全管理平台市场占有率第一,其中搭载的Sabre引擎提供了核心的安全检测能力。和很多互联网公司内部自建数据处理平台不同的是,Sabre更注重的是技术的工程化交付,因此在设计和实现上和一般基于Flink的业务系统相比会有较大差异。2.为什么要开发Sabre?随着网络应用规模和复杂度的不断提高,网络中传输的数据量急剧上升,网络攻防对抗日趋激烈,企业内部新的安全问题开始显现,实时关联分析引擎,作为NGSOC检测体系中的核心组件,也遇到了越来越多的挑战:(1)性能优化问题。主要针对随着新型攻击的不断出现,关联分析规则规模不断上升导致的性能问题。传统开源关联引擎往往加载几十条规则即达到了性能瓶颈,而NGSOC的应用场景中,关联引擎需要支撑规模上千的关联规则。在有限的硬件资源条件下,如何避免系统整体性能随规则条数上升而发生线性下降,成为关联引擎的一个主要挑战。(2)规则的语义扩展问题。在网络安全事件井喷式发生的今天,安全需求迅速扩展。为了能够在有限时间内对特定语义的快速支持,关联引擎的整体架构必须异常灵活,才能适应未来安全分析场景的各种需求,而基于开源关联引擎实现的产品会在激烈的需求变化时遇到很多问题。(3)系统扩展性问题。主要指分布式环境下节点的扩展。随着企业网络流量和业务资产的不断扩容,NGSOC的系统处理能力必须能随企业业务规模的不断扩张而动态扩展。未来的分布式关联分析引擎需要支持数百节点的规模,以能够与现有的大数据平台无缝集成。与Storm、SparkStreaming等流式计算框架相比,Flink具有编程接口丰富、自带多种Window算子、支持Exactly-Once、高性能分布式检查点、批流计算模式统一等优点。且Flink发展较为迅速,开源社区极为活跃,是目前最具发展潜力的流式计算框架,是未来实时计算执牛耳者。由于Flink为事件驱动的实时关联分析引擎在底层框架上提供了有力支持,因此奇安信的下一代关联分析引擎Sabre是基于Flink流式计算框架实现的。在选择了Flink之后,发现Flink开源方案直接应用于安全检测领域,仍有很大的技术障碍。和互联网企业内部使用的大型集群相比,NGSOC面向的企业级应用集群规模较小,硬件资源受限,且客户的定制需求较多,导致安全监测的规则要求更严格,引擎发布成本较高。但是,现有的Flink开源解决方案,或者需要根据业务需求进行改造,或者性能较差,均不能较好地解决上述问题。首先,原生Flink只提供了函数式编程模式,即需要直接编写复合特定业务需求的固定程序代码,由此导致开发测试周期较长,不便于动态更新规则,可复用性较弱,且不能从全局语义层面进行优化,性能较差。其次,Flink-CEP仅是一个受限的序列算子,在运行时需要将所有数据传输到CEP算子,然后在CEP算子中串行执行各个条件语句。这种汇集到单点的运行模式,较多的冗余数据需要执行条件匹配,产生了不必要的网络负载,而且降低了CPU利用率。再次,还存在一些非官方开源的轻量级CEP引擎,比如Flink-siddhi,功能简单,不是一个完整的解决方案。面向企业级的网络安全监测引擎具有一些特定需求,当前解决方案对此支持较差。比如,现实情况,客户对算子实例和Taskmanager概念较为模糊,真正关心的运行状态的基本单位是规则。而Flink监控页面显示的是算子实例及Taskmanager进程整体内存的运行状态,而在网络安全监控的业务场景中,对运行状态和资源的监控均需要细化到规则层面。其次,在算子层面,Flink原生Window算子,没有较好的资源(CPU/内存)保护机制,且存在大量重复告警,不符合网络安全监测领域的业务需求。再次,Flink缺乏一些必要算子,例如不支持“不发生算子”。一个较为常见的应用场景,某条规则指定在较长时间内没收到某台服务器的系统日志,则认为此台服务器发生了异常,需要及时通知用户。综上所述,现有解决方案应用于网络安全监测领域均会遇到问题,由此奇安信集团基于Flink构建了一种全新的CEP引擎。3.Sabre如何处理数据?上图为NGSOC的数据处理架构图,展示了整个系统的数据流。自下而上,NGSOC的数据处理过程由四部分组成,其核心是由“流式分布式关联分析引擎Sabre”构成的数据处理层PROCESS,且Sabre运行的硬件环境是由多个节点组成的分布式集群。右侧的规则配置管理模块供专业的安全人员使用,可通过类Visio图的界面较为友好便捷地配置规则;规则管理模块具有添加、删除、编辑和查找规则的功能,并可批量启动/停用多个规则,规则管理模块会将处于启动状态的有效规则统一发送给Sabre引擎。最上方的绿色部分为结果处理层RESULT,Sabre会将处理结果“告警”或“关联事件”发送给下级响应模块,实现响应联动、分析调查及追踪溯源等功能。最下方的蓝色部分为日志采集层COLLECT,主要有“网络流量日志采集器”、“设备及系统日志采集器”和“其他类型的日志采集器(比如:防火墙、入侵检测系统IDS、入侵防护系统IPS、高级威胁监测系统APT等等)”三大类。中间部分为日志解析层PARSE,网络流量日志和系统安全日志格式多种多样,须将上述两类原始日志数据格式化,而其他类型的日志(比如:威胁情报、漏洞、资产)本身即为格式化数据,最终所有格式化数据均需统一存储到高性能消息队列Kafka。4.Sabre的关键技术(1)系统架构上图为Sabre系统整体架构图。Sabre整体架构包含三大核心模块,中间是Sabre-server,左侧是配置端,右侧是Sabre运行端。核心数据流存在两条主线,红线表示规则的提交、编译、发布和运行流程。绿线表示状态监控的生成、收集、统计和展示流程。如图所示,此架构与Hive极为相似,是一种通用的大数据OLAP系统架构。下面详细介绍三大核心模块和两大核心数据流。首先,通过规则配置端创建规则,采用性能保护配置端修改性能保护策略,然后将任务所属的规则文件和性能保护策略文件一并推送到Sabre-server提供的REST接口,该接口会调用文件解析及优化方法构建规则有向无环图。接着执行词法语法分析方法,将规则有向无环图中各个节点的EPL转换为与其对应的AST(AbstractSyntaxTree,抽象语法树),再将AST翻译为任务java代码。最后调用maven命令打包java代码为任务jar包,并将任务jar包及基础运行库一并提交到Flink-on-YARN集群。Flink有多种运行模式(例如standaloneFlinkcluster、FlinkclusteronYARN、FlinkjobonYARN等),Sabre采用了“FlinkjobonYARN”模式,在奇安信NGSOC应用的特定场景下,采用YARN可统一维护硬件资源,并且使用FlinkjobonYARN可与Hadoop平台进行无缝对接,以此实现了很好的任务间资源隔离。在Sabre任务执行过程中,Kafka数据源向引擎提供原始事件。引擎处理结果分为回注事件和告警事件两类。告警事件会直接输出到目的Kafka,供下级应用消费。回注事件表示一条规则的处理结果可直接回注到下级规则,作为下级规则的数据源事件,由此可实现规则的相互引用。绿线流程表示任务执行过程中会定时输出节点的运行监控消息到Sabre-server的监控消息缓存器,然后监控消息统计器再汇总各个规则实例的运行监控消息,统计为整条规则的运行监控状态,最后通过Sabre-server提供的REST接口推送给规则监控端。(2)功能设计算子的设计和实现是构建CEP的重要组成部分。上图展示了Flink和Sabre算子的比较关系。包含三列:Flink原生算子、Sabre算子、两者之间的比较结果(相同、实现、优化、新增)。Sabre共有13种完全自研的核心算子,其中Datasource、CustomKafkaSink和CustomDatabase按照Flink接口要求做了具体实现,Filter、Key、Join和Aggregation按照Flink原有算子的语义做了重新实现,CustomWindow和Sequence在Flink原有算子语义的基础上做了优化实现。由于Flink原有FilterFunction算子只能简单返回布尔值,以致输出结果的控制能力较差,而重新实现的Filter算子可同时执行多种业务逻辑,将一个“原始事件”输出一个或多个“处理事件”。Sabre还实现了一种针对窗口的全局触发器Trigger,Trigger能够将多个子计算性算子组合为复杂表达式,并实现了具有GroupBy/Distinct功能的Key算子以适配此Trigger算子。众所周知,Join和Aggregation的时间范围由Window限定,而Flink原有Window算子不适合网络安全监测需求,为此Sabre设计了一种“自定义Window算子”,且重新实现了与“自定义Window算子”相匹配的Join和Aggregation算子。上图展示了Sabre算子间的关联关系。序列Sequence、聚合Aggregation、不发生NotOccur、流式机器学习StreamML和连接Join均属于Window执行时间包含的计算性算子。蓝色虚线表示引用动态数据,紫色虚线表示Filter无须经过Window可直连输出组件。如上图所示,为满足复杂场景需求,一种规则的输出可直接作为另一种规则的输入。通过这种规则拆分的方式,能分层构造较为复杂的“多级规则”。如:上面的“暴力探测”规则结果可以直接回注到下面的“登陆成功”规则,而无须额外的通信组件。(3)性能优化因为采用了Flink作为底层运行组件,所以Sabre具有与Flink等同的执行性能。并且,针对网络安全监测领域的特定需求,还做了如下的性能优化工作:1)全局组件(数据源、动态表)引用优化。由于Kafka类型的数据源topic有限,而规则数量可动态扩展,导致多个规则会有极大概率共用同一个数据源,根据EPL语义等价原则合并相同的数据源,进而可以减少数据输入总量及线程总数。2)全新的匹配引擎。序列Sequence算子采用了新颖的流式状态机引擎,复用了状态机缓存的状态,提升了匹配速度。类似优化还包含大规模IP匹配引擎和大规模串匹配引擎。3)表计算表达式优化。对于规则中引用的动态表,会根据表达式的具体特性构建其对应的最优计算数据结构,以避免扫描全表数据,进而确保了执行的时间复杂度为常量值。4)自定义流式Window算子。采用“时间槽”技术实现了乱序纠正功能,并具有可以实