资讯动态

多源异构数据融合驱动的网络安全态势评估体系解析

发布时间:2026/9/30 13:08:31 来源:尧图企业网站定制
简介这是一份面向网络安全研究人员、网络运维人员及高校相关专业师生的学术参考文献PDF格式全文共1个文件压缩包大小4.46MB。资料提出基于多源异构数据融合的网络安全态势评估体系针对单点网络数据难以准确检测恶意活动和评估网络状况的问题构建了流量探测、属性提炼、决策引擎、多源融合、态势评估五大模块。文中以BP神经网络作为决策引擎分析各数据源采用指数加权D-S证据理论融合多源输出并结合层次化网络威胁评估方法量化威胁状况实验显示多源融合可将攻击识别准确率提升至88.7%。已有267人学习下载适合需要了解态势评估建模思路、数据融合算法应用及实验验证方法的读者作为参考。1. 多源异构数据融合为什么单点探测器一定不够做网络安全的人大概都有过这种体验一台 Snort 在机房里跑得热火朝天报警刷了几万条你根本分不清哪些是真攻击、哪些是误报换个探测器看同一个流量结论可能完全相反。这不是工具不行而是单点检测的天然盲区——每个探测器只能看到网络的一个切片单独看都有道理合起来却凑不出完整画面。这篇《基于多源异构数据融合的网络安全态势评估体系》解决的就是这个问题用 Netflow、Snort、Suricata 三类异构数据源并行采集经 BP 神经网络分别做决策再用带指数权重的 D-S 证据理论把各路结果融合最终把攻击识别的准确率从单源的 85.2% 提到 88.7%然后按服务层、主机层、网络层三级结构给出态势曲线。适合正在做安全数据分析、态势感知平台或者想把手头 IDS 报警数据盘活成可量化的态势指标的从业者。2. 从流量到属性三类探测器的差异化特征工程2.1 为什么不能直接拿原始字段训练论文的流量探测模块部署了三类探测器Netflow 负责网络层流量统计Snort 和 Suricata 做入侵检测报警。三者本质是不同类型的传感器——Netflow 给你的是连接记录时间、协议、IP、端口、包数、字节数Snort 给你的是规则匹配出的报警事件Suricata 则是流量元数据加报警的混合体。如果用原始字段直接喂给分类器效果会很差。论文给了很直白的原因地址、端口、应用服务、时间这类离散属性对攻击类型几乎没有区分度。比如源 IP 的绝对值在训练集和测试集里分布不同模型学到的是这个 IP 是攻击而不是这种流量模式是攻击。所以它们设计了专门的统计算法把四种原始属性揉成网络连接属性。核心思想是不关心 IP 是谁关心在时间窗口内源 IP 与目的 IP 之间出现了多少次连接、端口分布是否异常。需要注意的是原始论文里三个探测器的基础属性设计不同Netflow 有 13 个字段偏流量统计Snort 有报警数量/报警类型Suricata 两者兼顾。融合的前提是各数据源属性不完全重叠如果三个源长得一模一样融合就没有增量信息了。2.2 网络连接属性的统计构造表 4 里的 8 个统计属性是整篇论文特征工程的核心我把它们合并整理一下属性名计算方式作用is_sm_ips_protsSip 与 Dip 相同且 Sport 与 Dport 相同则置 1识别同一对主机的重复连接ct_dst_ltm每 100 条记录中 Ltime、Dip 相同的数量目的 IP 热度ct_src_ltm每 100 条记录中 Ltime、Sip 相同的数量源 IP 热度ct_src_dport_ltm每 100 条记录中 Ltime、Sip、Dport 相同的数量源 IP 对目的端口的热度ct_dst_sport_ltm每 100 条记录中 Ltime、Dip、Sport 相同的数量目的 IP 对源端口的热度ct_dst_src_ltm每 100 条记录中 Ltime、Sip、Dip 相同的数量源到目的连接热度ct_srv_src每 100 条记录中 Sip、Serve 相同的数量源 IP 服务热度的聚合ct_srv_dst每 100 条记录中 Dip、Serve 相同的数量目的 IP 服务热度用 Python 构造这几个特征的做法大致如下import pandas as pd def build_connection_features(df, window100): 论文表4 网络连接属性构造基于时间排序后的流记录 df 需包含: Sip, Dip, Sport, Dport, Ltime, Serve 返回带 8 个统计特征的副本 df df.sort_values(Ltime).reset_index(dropTrue) # 1) 源目IP与源目端口是否相同 df[is_sm_ips_prots] ( (df[Sip] df[Dip]) (df[Sport] df[Dport]) ).astype(int) # 2) 滑动窗口内统计窗口大小100条记录 df[ct_dst_ltm] df[Dip].rolling(window, min_periods1).apply( lambda x: x.value_counts().iloc[0], rawFalse ) df[ct_src_ltm] df[Sip].rolling(window, min_periods1).apply( lambda x: x.value_counts().iloc[0], rawFalse ) df[ct_src_dport_ltm] df.apply( lambda r: int(((df[Sip] r[Sip]) (df[Dport] r[Dport])).sum()), axis1 ) # 其余 ct_ 特征同理按窗口内组合键计数 return df这段代码的要点在窗口设计。论文里用的是每 100 条记录一个窗口不是按时间窗口切分目的是让统计量跟随流量密度自适应——流量大时窗口时间短流量小时窗口时间长。rolling(window, min_periods1)保证前几条数据也有值避免冷启动。apply里取窗口内出现次数最多的值作为热度比固定阈值灵活。实际复现时我会用groupby代替apply性能会快很多但语义等价。另一个通用做法是把 100 条记录窗口换成 5 分钟时间窗口——论文后面做态势评估时用的是 5 分钟窗口但特征层面窗口按记录数走两套窗口各管各的别混用。2.3 数值归一化与非数值向量化为什么必须归一化看 Netflow 原始字段就明白了Bps比特数每秒动辄上万Sport源端口只有 0~65535如果直接进 BP 神经网络Bps 的梯度会完全压过端口属性数值变化小的属性等于被废掉。论文原文说得直白避免数值变化较大的属性覆盖数值较小的属性。from sklearn.preprocessing import MinMaxScaler, LabelEncoder # 数值型归一化到 [0, 1]消除量纲差异 num_cols [Pkt, Byt, Bps, Pps, Bpp, Ip_len] scaler MinMaxScaler() df[num_cols] scaler.fit_transform(df[num_cols]) # 非数值型向量化: 协议、服务、告警类型转为整数编码 for col in [Protocol, Serve, Attack_type]: df[col _enc] LabelEncoder().fit_transform(df[col].astype(str)) # 攻击类型作为标签也做编码 label_enc LabelEncoder() df[y] label_enc.fit_transform(df[Attack_type])这里要注意LabelEncoder有个坑它输出的整数带了大小关系比如tcp0, udp1会被模型误认为 udp 比 tcp 大。严格做法是用OneHotEncoder或pd.get_dummies。但论文里 BP 神经网络的输入层能接受编码向量所以实际操作中如果类别基数小协议就几种、告警类型几十种one-hot 更安全如果类别基数大可以先 embedding 再进网络但那属于后话。属性提炼模块的产出就是一张规范化后的特征表数值列全部在 [0,1] 区间非数值列变成稠密编码。这张表才是 BP 神经网络的真正输入。3. BP 决策引擎三层网络结构与三类数据源的训练差异3.1 为什么选 BP 而不是别的分类器决策引擎模块的任务是把核心属性映射到攻击类型。论文引用了 Hecht Nielson 的结论只含一个隐藏层的网络可以逼近闭区间上的任一连续函数。这说明 BP 在理论上能拟合任意复杂的属性到攻击类型的映射关系不需要预先假设数据分布。论文实验里用了 2 层隐藏层、每层 32 个神经元。为什么不用 1 层单隐藏层能逼近连续函数但要达到同样精度往往需要更多神经元两层结构在参数量适中的前提下对非线性特征的表达能力更强训练也相对稳定。在 UNSW-NB15 这个数据集上2×32 的配置是够用的——如果你复现时发现欠拟合先加神经元数而不是急着加深网络。3.2 前向传播与反向传播的数学链条网络结构定义输入层 m 个神经元隐藏层 h 个输出层 n 个。隐藏层第 j 个节点的输出是d_j f( Σ_m x_i * w_ji )输出层第 k 个节点的输出是ŷ_k f( Σ_h d_j * v_kj )均方误差是E 0.5 * Σ_n (ŷ_k - y_k)^2权值更新走标准梯度下降输出层权值 Δv_kj 由误差对输出的偏导链式乘出隐藏层权值 Δw_ji 还要再把误差从输出层往回调一层。学习率 η 控制每一步的步长论文公式里没有给出具体取值常见的做法是把 η 设在 0.01~0.1 区间配合自适应优化器使用。3.3 一个最小可跑的 BP 训练骨架用 PyTorch 复现论文的决策引擎结构大致如下import torch import torch.nn as nn class DecisionEngine(nn.Module): def __init__(self, in_dim, hidden32, out_dim10): super().__init__() self.net nn.Sequential( nn.Linear(in_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), # 论文用2层隐藏层 nn.ReLU(), nn.Linear(hidden, out_dim), nn.Softmax(dim1) # 输出为各类攻击概率 ) def forward(self, x): return self.net(x) # 每个数据源分别训练一个决策引擎 model_netflow DecisionEngine(in_dimnetflow_train.shape[1]) model_snort DecisionEngine(in_dimsnort_train.shape[1]) model_suricata DecisionEngine(in_dimsuricata_train.shape[1]) criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model_netflow.parameters(), lr0.005) for epoch in range(50): optimizer.zero_grad() out model_netflow(x_train) loss criterion(out, y_train) loss.backward() optimizer.step()代码里最关键的设计是三个数据源各自训练一个独立模型。不要把所有数据拼在一起喂给同一个网络——论文第三部分实验明确指出不同探测器对识别不同类型攻击的优势不同Netflow 擅长 Analysis 和 NormalSnort 擅长 Backdoor 和 WormSuricata 擅长 Dos这是多源融合的立论基础。拼在一起训练会把各源的优势互相稀释融合时反而没有差异化信息可用。输出层用Softmax(dim1)是因为后面 D-S 融合需要攻击类型概率作为证据输入。如果只做单模型分类用CrossEntropyLoss配合不带 softmax 的 logits 就行但这里 softmax 的概率值就是 D-S 理论里的基本概率分配少了这一步融合模块接不上。3.4 单源性能的边界在哪里论文表 8 给出了三个单源的基准Netflow 准确率 85.2%、Snort 80.2%、Suricata 79.5%误警率分别为 19.9%、26.1%、25.6%。注意 Netflow 虽然准确率最高误警率也最低但它对某些攻击类型是盲的Snort 准确率低但对 Backdoor、Worm 的识别能力是三个源里最强的。这说明评估一个决策引擎好坏不能只看总准确率。我复现这类体系时的习惯是先给每个数据源单独算混淆矩阵确认每个源在哪些攻击类别上有优势再进入融合阶段。如果某个源所有类别都表现平庸那它大概率是特征工程出了问题而不是融合能救的。4. 复现避坑指南训练阶段最容易翻车的五个位置4.1 类别不平衡导致模型假装工作现象训练出的 BP 在测试集上准确率有 80% 多但看混淆矩阵发现它把大部分攻击都判成了 Normal靠猜多数类刷分。原因UNSW-NB15 的 5% 子集中 Normal 流量占比很高BP 用交叉熵损失训练时多数类的梯度主导了参数更新模型学到的实际上是全预测 Normal 损失也不大。这正是论文里误警率一直降不下来的根因之一——不仅仅是融合算法的问题训练阶段就偏了。解决对少数类做加权采样或给损失函数加类别权重。CrossEntropyLoss(weighttorch.tensor([...]))即可实现。另外建议训练集做分层抽样保证每个攻击类别在训练和验证集里的比例一致。4.2 非数值属性直接进网络现象模型训练 loss 不下降或者收敛后精度远低于论文的 85%。原因把 IP 地址、协议名、告警类型这种字符串属性直接塞进了nn.LinearPyTorch 根本不会帮你做编码模型把一个字符串当成了一个浮点数特征梯度毫无意义。解决严格按 2.3 节的流程走——数值列归一化、非数值列 one-hot 或 label 编码。这里有个实操细节告警类型这种高基数类别one-hot 会让输入维度爆炸可以先用CountVectorizer按出现频率筛出 top-K 类别其余归入 unknown 类。4.3 滑动窗口统计泄漏未来信息现象特征工程的准确率在训练集上极高测试集上骤降。原因rolling窗口和apply的组合如果没有sort_values(Ltime)排序窗口内会混进乱序记录更隐蔽的问题是如果窗口按整份文件滚动而不是按主机分组滚动同一主机的连接会被其他主机的记录打断统计属性失去语义。解决构造特征前务必按时间戳排序按 Sip 或 Dip 分组后再单独滚动。论文的 100 条窗口是全局窗口实际操作中我一般会先按主机分组再做窗口统计这样ct_src_ltm才能真实反映单个主机的连接热度。4.4 误警率偏高是数据集的固有属性不要死磕现象融合后误警率 13.7%你反复调阈值想降到 10% 以下结果准确率也跟着掉。原因论文表 9 引用了其他团队在同一数据集上的结果——决策树 15.8%、逻辑回归 18.5%、朴素贝叶斯 18.6%、ANN 21.1%全部高于 15%。UNSW-NB15 里部分攻击流量和正常流量在特征空间高度重叠这个误警率下界是由数据集本身决定的。解决接受 13%~15% 的误警率作为这个数据集的合理区间。评估体系是否有效重点看融合相对单源是否改善了误警率19.9%→13.7%而不是追求绝对数值。我在复现时还会额外看每个攻击类别的召回率特别是 Dos、Exploit 这类高危攻击漏报比误报更危险。4.5 三个数据源的时间对齐不一致现象Netflow 的窗口是 5 分钟聚合Suricata 的报警是秒级事件融合时两者对不上同一时间窗口内 Netflow 说没有攻击、Suricata 报了 50 条告警。原因流量探测模块的三种探测器采集粒度天然不同Netflow 偏统计、IDS 偏事件不做时间对齐就直接融合等于把不同时间尺度的信息强行叠加。解决统一先按 5 分钟时间窗口论文实验就是 33000 秒切成 110 个窗口聚合所有源的属性。Netflow 统计特征直接落在窗口内Snort/Suricata 报警按窗口内条数聚合成报警数量、报警类别分布。代码上就是df.groupby(pd.Grouper(keyLtime, freq5min))之后分别聚合再把三个源按窗口笛卡尔对齐。5. 指数加权 D-S 融合PSO 如何把准确率推到 88.7%5.1 经典 D-S 证据理论的困境多源融合模块要做的事是三个 BP 决策引擎各自输出一个攻击类型概率向量把它们合成一个更可信的结果。D-S 证据理论天然适合这个场景但经典 D-S 合成规则有一个著名的问题——当两个证据源对同一命题给出冲突意见时合成结果可能违背直觉。论文采用的是指数加权变体每个证据源的第 i 类攻击概率 m_j(Ai) 被提升到指数幂 w_ji 之后再做乘积。权重 w_ji 不是拍脑袋定的而是用粒子群优化算法搜出来的。这个设计的意图是某个数据源在某一类攻击上更有优势就给它更高的指数权重让它在融合结果里说话更响亮。5.2 指数加权公式与归一化融合后的第 i 类攻击概率是m(Ai) Π_j m_j(Ai)^w_ji / KK 是归一化常数K Σ_i Π_j m_j(Ai)^w_ji这里 g 是数据源数量本实验为 3n 是攻击类型数UNSW-NB15 取 10 类含 Normal。指数权重 w_ji 是优化变量不是先验给定的——PSO 在 [0,1] 范围内搜索每个数据源对每类攻击的权重目标是让融合概率和真实标签的均方误差最小argmin Σ_i (m(Ai) - y_i)^25.3 粒子群优化器的实现import numpy as np def pso_fusion_weights(evidence, y_true, swarm_size100, dimNone, epochs60): evidence: shape [n_samples, n_sources, n_classes] 三个BP引擎的softmax输出 y_true: one-hot 真实标签 返回: 每个源每类攻击的指数权重矩阵 [n_sources, n_classes] n_sources, n_classes evidence.shape[1], evidence.shape[2] dim n_sources * n_classes # 初始化粒子位置 ∈ [0,1]速度随机 x np.random.rand(swarm_size, dim) v np.random.rand(swarm_size, dim) * 0.1 p_best x.copy() g_best x[0].copy() def fusion_loss(pos): w pos.reshape(n_sources, n_classes) # 指数加权乘积: m(Ai) Π m_j(Ai)^w_ji / K logits np.sum(w[np.newaxis, :, :] * np.log(evidence 1e-12), axis1) m np.exp(logits) m / m.sum(axis1, keepdimsTrue) return np.mean((m - y_true) ** 2) for _ in range(epochs): for i in range(swarm_size): loss fusion_loss(x[i]) if loss fusion_loss(p_best[i]): p_best[i] x[i].copy() g_best p_best[np.argmin([fusion_loss(p) for p in p_best])] # 速度更新: v c3*v c1*r1*(p_best - x) c2*r2*(g_best - x) c1, c2, c3 1.5, 1.5, 0.5 r1, r2 np.random.rand(dim), np.random.rand(dim) v c3 * v c1 * r1 * (p_best - x) c2 * r2 * (g_best - x) x np.clip(x v, 0, 1) return g_best.reshape(n_sources, n_classes)几个值得说清楚的参数细节。PSO 的群体规模论文给了 100搜索空间限定在 [0,1] 是因为指数权重必须非负超过 1 的权重会放大证据差异容易让融合结果被单一源主导。速度更新里的 c1、c2 是推向局部最优/全局最优的权重c3 是惯性权重常规取值是 c1c21.5、c30.5论文公式里也是这个结构。代码里np.log(evidence 1e-12)是为了防止 evidence 里出现 0 导致 log 崩掉——softmax 输出理论上不会严格为 0但浮点精度下可能下溢加一个极小量是稳妥做法。融合后的效果论文表 8 写得很清楚指标NetflowSnortSuricataD-SPSO-DS准确率85.280.279.587.888.7误警率19.926.125.614.913.7注意两个增量经典 D-S 已经把准确率提到 87.8%说明融合机制本身就有效PSO 只把准确率再推高了 0.9 个百分点但把误警率压到了 13.7%。这说明指数权重的价值主要在抑制误报——让优势数据源在对应攻击类别上权重更大从而减少弱势数据源的胡说八道。这也是为什么我会强调先分析单源混淆矩阵你只有知道每个源在哪类攻击上强回头看 PSO 搜出来的权重矩阵才能验证结果是否合理。融合阶段常见的一个误用是直接对三个源的 softmax 输出做平均。平均是最粗暴的融合牺牲了各源的差异化优势。另一个误用是融合后不再归一化直接拿去和阈值比这类错误会导致态势评估模块的服务层态势值虚高。6. 层次化态势评估从威胁量化到三级曲线下钻6.1 威胁等级划分与权系数量化态势评估模块要回答的问题是融合出某主机正在遭受 3 类攻击概率分别是 0.6/0.3/0.1之后这个信息怎么变成一个可以用来决策的数值论文的路径分两步先按 Snort 的报警规则把攻击分成高中低三档再用权系数理论算出每档对应的威胁因子值。威胁等级划分原则可以压缩成一张表攻击目标具体行为威胁等级计算机权限获取管理员/普通用户控制权限、执行代码高隐私信息获取系统内部信息中带宽消耗拒绝服务、消耗带宽中网络扫描扫描获取网络信息低威胁因子值不是手动指定的而是用一个离散化的权系数函数算出来的。n 为攻击等级个数i 为排列顺序当 i 位于序列前一半时威胁因子大于 0.5后一半小于 0.5中间档恰好等于 0.5。论文实验里的取值是高威胁 0.726、中威胁 0.611、低威胁 0.389Normal 为 0。这个量化的好处是给了严重程度一个连续数值后续逐层加权才有运算基础。6.2 三层态势的递进计算三层评估是自底向上的。服务层某台主机上第 j 个服务的态势值是时间窗口内所有攻击的概率乘以威胁因子再累加s_kj(t) Σ m(attack_i) * 10^f(attack_i)注意这里有个放大系数 10。为什么是 10论文没有解释但这种指数放大在安全场景里有实际意义——高危攻击哪怕概率低贡献的态势值也不能被中低危攻击的数量淹没。如果只有 2 个高危攻击各 0.3 概率线性累加只有 0.6很容易被 20 个低危攻击各 0.1的 2.0 压过这是不合理的指数放大让高危攻击的少量出现就能在曲线上形成尖峰便于管理员感知。主机层态势是服务层态势向量与本机服务权值向量的加权和服务权值由使用该服务的用户数和频率归一化得到网络层态势是各主机态势向量与主机权值向量的加权和主机权值同理。这三级关系用一段短代码可以表达def eval_situation(svc_probs, threat_factor, service_weights, host_weights): # svc_probs: [host, service, attack_type] 融合概率 # 服务层: 概率 * 10^威胁因子 累加 svc_situation (svc_probs * (10 ** threat_factor)).sum(axis2) # 主机层: 服务态势 * 服务权值 加权求和 host_situation (svc_situation * service_weights).sum(axis1) # 网络层: 主机态势 * 主机权值 加权求和 net_situation (host_situation * host_weights).sum() return svc_situation, host_situation, net_situation这段代码对应论文公式 (12)(13)(15)。三个参数的形状得事先对齐svc_probs是三维张量threat_factor是攻击类别维度的向量service_weights和host_weights分别是服务和主机的权值向量全部要在时间窗口内按 5 分钟聚合。6.3 验证技巧从网络层曲线反向定位问题主机论文实验部分展示了三个层面的态势曲线服务层能看出某主机上 HTTP 服务一天内遭受 2 次强烈攻击主机层能对比三台主机的受攻击程度网络层能看到全天 4 次较大波动。我的复现习惯是反向验证先看网络层曲线找到波动的时间窗口再下钻到主机层看哪台主机的态势值在那个窗口内抬升最后落到服务层确认是 DNS、HTTP 还是 SMTP 出了问题。这样做的好处是过滤掉了大量不重要的低危攻击——网络层曲线能自动把大量低危攻击累积和少量高危攻击区分开因为高危攻击有 10 的指数放大。当初我按这个流程复现时最大的感受是单源时代看报警列表看到眼花三层体系下只需要盯住曲线突变点再下钻定位效率提升是肉眼可见的。等到我自己搭这套体系时会在融合概率输出后额外加一个高危攻击专属通道——把威胁因子大于 0.7 的攻击单独列一条实时告警不走态势曲线因为态势评估本质是滞后几分钟的统计而高危攻击需要即时响应。从那以后我每次做态势评估系统的验证都强制走一遍网络层找波动 → 主机层定位 → 服务层确认 → 高危攻击单独排雷的完整循环这个习惯帮我避开了好几回漏报。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑