概述
目的
通过持续对流量数据的监测,不断丰富及提取合适的流量特征,以实时检测流量异常
几种主要结果:
- scanmon
- ddosmon
- 暴力破解/垃圾邮件服务器等
Pivot模型
netflow数据是流量的摘要数据,因此通过netflow来检测流量异常也就只能通过摘要统计来提取特征。
一条原始netflow数据形如:
|
|
这样的数据,只有基本的发生时间,持续时长,来源/目的 的IP:端口等等基本信息。
一般情况下,单条数据无法形成有效的事件鉴别特征,如果我们想深入观察某个IP的状况,我们需要累积一定时间窗口内的与该IP相关的所有数据来观察,比如针对目的IP 189.203.188.074,我们累积一段时间的来源流量可以得出如下统计数据:
我们可以看到,来源IP比较分散,但是来源Port固定为53和碎片0端口,同时,很多包都是1500 MTU的满包状态,我们就有充足的信心来说,这是一个DNS反射放大攻击事件,是典型的大量的被利用的反射节点给受害者目的IP发送超过1500的大包导致的流量形态。
双向
针对一个IP,我们要想观察它是否异常,我们就需要观察它进出两个方向的流量:
- 如果是一个Scanner,可能一段时间内只看到它出去的流量,而看不到流向它的流量
- 如果是一个被DDoS目标,可能一段时间内只看到它进入的流量,而看不到它出去的流量
多层
同时针对一个IP,观察需要按照IP/Proto/Port来分层观察流量:
- 一个IP上TCP 80端口是正常服务,但是被攻击的是90端口,如果不根据端口来区分观察流量可能会miss
- 一个IP上TCP 80端口正常服务,但是被攻击的是UDP流量,如果不根据协议来区分观察流量可能会miss
多触发
一般情况下,聚合10分钟的数据,然后整理成所需的格式push到后续流程做检测就够了,但为了数据的时效性以及查全查准,一共有三种检测触发器:
- STWPop:STW for Sliding Time Window,固定时间窗口流量spike触发检测
- EarlyPop:一个IP一个时间窗口内最开始出现的部分流量
- AETWPop: AETW for Auto-Extend Time Window, 当一个固定时间窗口内流量太小,自动扩展更多个时间窗口的数据来触发检测
规则
特征概述
根据我们上述“双向-多层-多触发”模型,任何一个规则条件都可以简单概括为如下:
针对一个IP/IP-Proto/IP-Proto-Port,其:
- 来源/目的
- IP/Proto/Port/Flow/PackageNum/PackageSize/Duration
- 的unique/sum/dispersion/top
是什么
比如上面我们给出的UDP反射放大攻击的case,我们提到“来源IP比较分散,但是来源Port固定为53和碎片0端口”
这里其实需要映射为三个“与关系”的条件:
- 针对IP 189.203.188.074,其来源IP的dispersion介于[0-5]之间(这里的[0-5]是离散的数值表示)
- 针对IP 189.203.188.074,其来源Port的Top1等于53
- 针对IP 189.203.188.074,其来源Port的Top2等于0
规则条件说明
规则条件基本上都是 Calc_DirectionORPosition_Item 的形式。
DirectionPosition
- in: 进入的流量
- self_as_dst: 自身作为目的的流量
- self_as_src: 自身作为源的流量
- ot: 出去的流量
比如如下5条流量:
整理成我们的Pivot模型后,DirectionPosition的位置如下:
Item基本概念:
- duration: flow持续时长,一个5元组flow数据的持续时长
- pkgnums:一个flow中的package数,数字越大,说明同一个flow中传输的package越多
- pkgsize: 一个flow中的package的平均大小,数字越大说明同一个flow中传输的package越大
- peer: IP+Port是一个peer
- ipv4:IP
- ip_b:IP/16
- ip_c:IP/24
- port:port
- tf: TFlags整体
- fin/ack/syn/psh/rst/urg/nul: TFlags中对应的单独的一位
所有枚举型都会被整理为ordered-count-map,类如{A:100, B:80, … N:1},表示A出现100次,B出现80次,。。。 N出现1次,并且按照大小排序,Calc基本都是根据ordered-count-map的计算
Calc基本概念:
- lens:unique(ordered-count-map)
- diss:离散度,0-9999,数字越小说明越分散,5为比较分散,10为比较聚集,20以上为非常聚集。这个数字的step要根据现实流量的态势来调整
- tops: ordered-count-map的最大的key
- top2: ordered-count-map第二大的key
- avgs: ordered-count-map中value的均值,或者sum([k * v for k, v in ordered-count-map])/len(ordered-count-map)
- span: ordered-count-map中最大最小的key的跨度
- rate: 比率,往往是和TFlags结合来确定进出tflags的比率
举例:
- lens_in_ipv4: 进入流量中ip的unique个数
- diss_ot_port: 出去流量中port的离散程度
- tops_in_port: 进入流量中最多的port
- avgs_ot_duration: 出去流量持续时长的均值
- rate_in_syn: 进入流量的SYN的比例
规则实例
上面说的规则条件都是单个的条件,一条规则实际是多个条件的“与”结合
|
|
上面是一条完整的规则,attr表示为规则属性,cond表示为规则条件,按行依次解释为:
|
|
规则集
如上一条规则只能捕获一种或几种类型的“udp@attack@amp_flood_target”事件,但是不能捕获所有的“udp@attack@amp_flood_target”事件。同一种事件,在不同的场景下可能有不同的数据形态,在不同的阶段可能有不同的数据形态,因此针对某一特定事件,我们需要多条规则来覆盖所有的场景,以期达到更高的检出率。多条规则之间是“或”的关系,一次匹配,是匹配所有可疑的规则,只要能命中其中任意一条,我们便可判定为真。
同时,存在某些场景下,不同的事件类型但是数据形态非常相似,只有细微的差别,这时候为了规则运维的方便,有一个priority属性,一条数据匹配到多个规则,只会取priority最大的结果。
架构
整体数据流程可以简单的分为“分发 - 汇集 - 匹配 - 输出”四个步骤。
- 分发:接受不同采集节点的数据,按照一定规则hash(ip)的方式分发数据到汇集的节点
- 汇集:持续累积给定时间窗口的数据,整理为上述的模型数据,并依照上述模型中的触发条件,将数据POP出来,给到后续匹配流程做检测
- 匹配:接受数据,根据给定的规则,检测具体的事件
- 输出:最终结果事件的输出记录
原始数据分发
我们的模型是要针对某一个IP采集进/出两个方向的流量,而一个IP要么出现在src的位置,要么出现在dst的位置,这就意味着,对于一个 A->B 的flow,我们既要将其发送给A对应的汇集点,也要将其发送给B对应的汇集点。
原始数据聚合
聚合的过程是根据数据到达的时间实时进行的,几个要点:
- 默认聚合过程是汇聚到IP-Proto-Port级别,而IP/IP-Proto级别的数据,是在STWPop的时候动态计算的,这样可以节省内存资源消耗
- 由于有AETWPop的存在,所以一个固定时间窗口过去后,“即没有多到可以直接判断,又没有少到可以忽略的”这部分数据需要留存下来参与下一次的聚合过程
- 由于数据分布不均的原因,同一个聚合点缓存数据的Flush实际有两个触发条件,一个是配置的TimeWindow的大小,一个是聚合key的最大值。正常情况下都是前者起作用,但后者可以保证即便某个点数据爆炸,系统还能保持稳定运行
模型数据匹配
匹配过程是一个 “white-black-gray” 串联匹配过程
- white: 用以初步过滤一些明显的不管新的数据
- black: 用以匹配出我们已知的恶意事件
- gray: 对white/black以外的数据进行历史流量建baseline,然后找出可疑的异常
三个节点都是可选的,动态配置。
结果数据输出
略。
附录
规则可用属性
- tag: 事件类型,基本为proto@event_type@detailed_type 格式
- index: 规则组,如果想针对不同的数据过不同的规则集
- priority: 优先级,规则默认优先级是0,如果确认一条规则最精确最准,可以设置一个高优先级,这样会覆盖其他规则的匹配
规则可用条件
大部分规则都符合“规则-规则说明”中的格式,部分特殊的加了额外说明
- accu: 数据聚合级别,3是IP-PROTO-PORT,2是IP-PROTO,1是IP
- prot: protocol 协议
- port: 端口
- proc_step: 处理阶段,1是STWPop和AETWPop,2是EarlyPop
- time_win: AETW扩展了几个时间窗口
- in/ot_fsum: 进/出的flow总计
- in/ot_psum: 进/出的package总计
- in/ot_bsum: 进/出的bytes总计
- diff_flow_io: 进出flow差值
- diff_flow_oi: 出进flow差值
- in/ot_locals_spike: 进/出短时间窗口(1小时)spike幅度
- in/ot_global_spike: 进/出长时间窗口(1天)spike幅度
- in/ot_spike: in/ot_max(locals_spike/globals_spike)
- in/ot_spike_type: flow spike/packages spike/bytes spike
- in/ot_ipv4_count_avg: 进/出IP的平均出现次数
- in/ot_ipv4_count_top: 进/出IP中出现最多的次数
- rate_io_avgs_pkgsize: 进/出包大小比率
- tops_nzport_io_equal: 进/出流量中最大的非0端口是否一致
- 此处省略100条条件