资讯动态

机器学习DDoS入侵检测毕设指南:数据、特征与实时部署

发布时间:2026/10/3 13:12:39 来源:尧图企业网站定制
简介面向毕业设计场景的 DDoS 入侵检测机器学习源码包包含逻辑回归、正则化逻辑回归、多类别逻辑回归三种算法的 Python 实现适合需要完成入侵检测相关课设或毕设的计算机、网络安全专业学生参考。压缩包共 4 个文件其中 3 个 py 文件分别对应三种分类模型可直接运行并在此基础上扩展实验另有 1 个 docx 毕业设计简述文档用于梳理算法原理与实验思路。整个压缩包仅 240KB结构轻量便于快速下载、阅读和二次开发。目前已有 674 人学习下载。通过这份源码读者可以掌握逻辑回归在 DDoS 攻击检测中的应用链路包括特征处理、模型训练、分类评估等关键步骤对照简述文档也能更清晰地理解正则化对模型泛化能力的提升作用。对正在撰写毕业设计或准备算法竞赛的同学而言这份材料兼顾代码与文字说明是实用参考资料能够减少从零搭建实验环境的时间。1. 机器学习DDoS入侵检测毕设选它拼的不是模型而是数据做毕业设计选“基于机器学习的DDoS入侵检测”很多人第一反应是“我要训练一个模型能区分正常流量和攻击流量”。真做下去才发现模型只占整个工作量的一小部分真正卡人的是数据怎么来、特征怎么算、标签怎么打、以及如何让检测从离线脚本变成能演示的实时系统。这套技术方案解决的就是这件事用Python把“流量采集 → 特征提取 → 模型训练 → 在线检测”整条链路打通适合网络工程、网络空间安全、计算机科学方向的学生也适合想快速上手入侵检测方向的从业者。我把做这个毕设的完整思路写出来从数据集选型到训练踩坑给出一条能复现、能答辩的路径。2. 数据集与特征工程从pcap到CSV的落地路径2.1 选数据集CIC-IDS2017、CIC-DDoS2019 还是自己抓包机器学习DDoS检测的公开数据集里最常用的是加拿大网络安全研究所CIC发布的 CIC-IDS2017 和 CIC-DDoS2019。CIC-IDS2017 包含正常流量和多种攻击流量DDoS、PortScan、Botnet、Web攻击等特征是已经用 CICFlowMeter 提取好的每行是一个网络流一共 80 多个数值特征直接用 pandas 读进来就能训练适合做分类和入侵检测。CIC-DDoS2019 是专门的 DDoS 数据集攻击类型非常全涵盖 TCP SYN flood、UDP flood、反射放大攻击等流量背景更贴近真实场景但文件体积非常大单机训练通常要抽样。还可以用 UNSW-NB15特征是 49 维包含攻击类别和记录标签体积小不少适合快速跑通流程。如果学校实验室有多余机器也可以自己抓包生成数据集常见做法是正常流量用实验室的 HTTP、DNS、SSH 服务自行产生攻击流量在受控实验环境里用 hping3、Scapy 或 Python 脚本构造 SYN flood、UDP flood。这里的红线一定要记住所有攻击流量生成实验只允许在你自己申请过的实验环境或学校靶场里做抓包也只针对本机回环口或实验室网关绝对不能对公网目标执行任何探测或流量发送。下表是我会推荐给备选数据集的对比数据集特征维度攻击类型文件规模适合场景CIC-IDS201780DDoS、PortScan、Web、Botnet中等偏大多分类综合入侵检测CIC-DDoS201980DDoS 专项反射/放大类型丰富很大DDoS 专项检测、细粒度分类UNSW-NB1549混合攻击含 DDoS较小快速跑通流程、新手入门选数据集的原则就一条先看你毕设题目怎么写的。题目里只有“DDoS入侵检测”那就选 CIC-DDoS2019工作量和答辩深度都足够题目写成“基于机器学习的网络入侵检测系统”选 CIC-IDS2017 更合适因为还有多分类的空间。2.2 特征提取五元组、流统计与时间窗CIC 数据集已经把特征提好了但毕设不能只“喂现成的数据”因为答辩老师一定会问“如果换个环境你的模型怎么感知新流量”所以自己提取特征是必须讲清楚的部分。网络流特征计算的逻辑是把五元组相同的连续包聚成一条流然后统计这条流里包的到达间隔、包长均值、方差、持续时间、上行下行字节数等。CICFlowMeter 是提取这些特征的常用工具可以把 pcap 文件转成 CSV。用 Python 做流特征提取也有简单方案用 Scapy 读取 pcap 后按流聚合。下面是一个精简版的分组聚合框架只统计最核心的几个特征完整实现需要自己补全时间窗口和标志位处理from scapy.all import rdapcap from collections import defaultdict import time def extract_flow_features(pcap_path): packets rdapcap(pcap_path) flows defaultdict(list) for pkt in packets: if pkt.haslayer(IP) and pkt.haslayer(TCP): key ( pkt[IP].src, pkt[IP].dst, pkt[TCP].sport, pkt[TCP].dport, TCP ) flows[key].append(pkt) flow_features [] for key, pkts in flows.items(): pkt_lengths [len(pkt) for pkt in pkts] timestamps [float(pkt.time) for pkt in pkts] duration max(timestamps) - min(timestamps) flow_features.append({ src: key[0], dst: key[1], sport: key[2], dport: key[3], packet_count: len(pkts), byte_count: sum(pkt_lengths), avg_packet_len: sum(pkt_lengths) / len(pkts), duration: duration, packets_per_second: len(pkts) / duration if duration 0 else 0 }) return flow_features # 用法features extract_flow_features(syn_flood.pcap)这段代码的逻辑是先遍历 pcap 里的每个包用 IP 和 TCP 层的信息组成五元组没有 TCP 层的 UDP 包需要单独按 UDP 分支处理实战中要把 TCP 和 UDP 分开避免把不同协议算进同一条流。时间窗口也比单条流更难线上检测不可能等整条流结束再判断只使用过去 N 秒的滑动窗口这是很多毕设翻车的点。参数上需要关注avg_packet_len和packets_per_second这两个特征。SYN flood 的特征是短包多、每秒包数极高UDP flood 的特征是 packet_count 大、包长相对固定慢速 DDoS 的特征是 packets_per_second 很低但持续时间长。所以单靠统计学特征会漏掉慢速攻击后面还要补充源端口变化率、TCP 标志分布等行为特征。2.3 标注与清洗把多分类标签压成二分类的注意点CIC-IDS2017 的 CSV 里最后一列是 Label颗粒度很细比如“DDoS”“Heartbleed”“PortScan”“BENIGN”。毕设题目是 DDoS 入侵检测建议把标签重映射成二分类正常流量是 0所有攻击流量是 1。如果题目是“多类型攻击识别”才保留多分类标签。标签清洗有个常见坑CSV 的 Label 列里有空格和大小写不一致比如DDoS或ddos都出现训练前要 strip 掉空格并统一小写。另外数据集里某些攻击类样本量极少比如 Heartbleed 只有几十条这种类在二分类里直接归为 attack 类别可以但放到多分类里就是严重不平衡问题。清洗代码一般用 pandas 处理import pandas as pd df pd.read_csv(IDS2017.csv, encodinglatin1) df[Label] df[Label].str.strip().str.lower() df[label_binary] (df[Label] ! benign).astype(int) # 处理无穷值和缺失值 df df.replace([float(inf), -float(inf)], 0) df df.fillna(0) # 删除完全无意义的列比如目的端口在某些样本里是 NaN drop_cols [c for c in df.columns if port in c and df[c].isnull().mean() 0.5] df df.drop(columnsdrop_cols, errorsignore) print(df[label_binary].value_counts())逻辑说明二分类映射很直接(df[Label] ! benign).astype(int)把非良性流量全部置为攻击样本。重要的一步是replace([float(inf), -float(inf)], 0)CIC 特征文件里有很多除法后产生的 Infinity直接进入 sklearn 会报错这是最容易被忽略的一行。3. 模型选型与Python训练脚本随机森林与XGBoost的取舍3.1 为什么首选随机森林和XGBoost而不是深度学习DDoS 检测的特征是典型的表格型数据高维稀疏、特征之间关系复杂但没有明显的空间结构。这个场景下随机森林和 XGBoost 比深度学习模型更容易出效果理由有三条。第一训练成本低一台普通笔记本跑 CIC-IDS2017 抽样后的几万条样本随机森林几分钟内就能出结果而神经网络光预处理和调参就至少多花一周。第二可解释性好答辩老师问“你的模型为什么认为这是攻击”你可以直接看特征重要性排序而神经网络只能给权重矩阵。第三树模型对不平衡数据更友好随机森林支持class_weight参数XGBoost 自带scale_pos_weight可以针对攻击样本少的情况做调整。深度学习也不是完全不用如果毕设题目写了“基于深度学习的DDoS检测”可以先用随机森林跑出基线结果再用 LSTM 或一维卷积对比这样故事完整、工作量足。但如果只是硬凑神经网络调参过程非常痛苦这就是过来人的血泪经验。模型优点缺点DDoS检测里适用性随机森林训练快、特征重要性可解释、抗过拟合在线预测速度一般最适合做基线XGBoost精度高、可调参数多、自带正则化调参有门槛、慢速训练最推荐作为最终模型逻辑回归速度快、可解释性最强无法自动捕捉非线性特征适合做对比实验LSTM/CNN能自动提取时序特征数据需求大、训练时间长加分项做对比实验3.2 训练脚本数据切分、交叉验证与特征重要性我一般会把训练代码固定成一套模板数据集换哪个都不影响主流程。下面是完整可运行的核心训练脚本用随机森林做基线XGBoost 做优化最后输出特征重要性import pandas as pd from sklearn.model_selection import train_test_split, cross_val_score from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix import xgboost as xgb df pd.read_csv(data_clean.csv) feature_cols [c for c in df.columns if c not in [Label, label_binary, Flow ID]] # 按时间顺序切分不打乱随机种子避免流量时序信息泄漏 X df[feature_cols].values y df[label_binary].values X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) # 基线模型随机森林 rf RandomForestClassifier( n_estimators200, max_depth20, min_samples_leaf4, class_weightbalanced, n_jobs-1, random_state42 ) rf.fit(X_train, y_train) y_pred_rf rf.predict(X_test) print(Random Forest Report:) print(classification_report(y_test, y_pred_rf)) # 进阶模型XGBoost xgb_model xgb.XGBClassifier( n_estimators200, max_depth8, learning_rate0.05, scale_pos_weight(y_train 0).sum() / (y_train 1).sum(), eval_metricaucpr, use_label_encoderFalse ) xgb_model.fit(X_train, y_train) y_pred_xgb xgb_model.predict(X_test) print(XGBoost Report:) print(classification_report(y_test, y_pred_xgb)) # 输出特征重要性 importance pd.Series(xgb_model.feature_importances_, indexf{c} for c in feature_cols) print(importance.sort_values(ascendingFalse).head(20))脚本设计上有几个点要说明。stratifyy确保训练集和测试集的正负样本比例一致这在 DDoS 检测里非常重要因为公开数据集的攻击流量占比通常只有百分之十几不 stratify抽样出来的测试集可能一条攻击都没有。class_weightbalanced和scale_pos_weight是应对类不平衡的核心参数前者是 sklearn 自动调整权重后者是手动把正类的权重调成负类样本数除以正类样本数。如果攻击样本只有 10%scale_pos_weight大约设为 9模型会显著提高对攻击样本的召回率代价是误报率略升。注意feature_cols的排除列表里一定要删掉“Flow ID”和“Label”否则特征里混入样本标识符和标签模型会出现虚高分数测试集上 99.9% 的结果都是假象。3.3 用测试集和混淆矩阵判断“能不能过毕设”的指标很多学生只盯着 accuracyDDoS 数据集里正常流量占多数模型把所有样本都预测为正常accuracy 也可以到 85% 以上但这种模型没有任何价值。答辩老师看的是三个数字对攻击样本的召回率、误报率正常被识别为攻击的比例、以及 F1 值。合格的毕设标准大概是二分类 DDoS 检测里攻击样本召回率至少 95% 以上误报率控制在 5% 以下F1 值高于 0.9。如果达不到这个水平先去检查特征清洗和标签泄漏问题这两个原因占了 90% 的翻车案例。同时输出混淆矩阵这个才是答辩时的硬货import matplotlib.pyplot as plt import seaborn as sns from sklearn.metrics import confusion_matrix cm confusion_matrix(y_test, y_pred_xgb) sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabels[Benign, Attack], yticklabels[Benign, Attack]) plt.xlabel(Predicted) plt.ylabel(True) plt.savefig(confusion_matrix.png, dpi150)代码的逻辑很直接最需要留意的是横纵坐标的标签顺序confusion_matrix默认按类别顺序排列如果 LabelEncoder 改变了类别顺序图上的标签就会颠倒答辩被问到时解释得多费很多口舌。提前用np.unique(y)确认顺序比事后看图快得多。4. 实时检测与API封装把模型接到流量入口4.1 离线检测到在线检测的架构差异训练脚本跑通的只是离线检测也就是“读保存好的 CSV预测每一行”。毕业设计演示时老师大概率会让你现场抓一段流量实时判断是否包含 DDoS 攻击。从离线到在线唯一的原则是特征计算的逻辑必须完全一致。离线训练时你用了整条流的持续时间、整条流的包长度均值在线预测时由于流量还在持续进入你根本不知道整条流的结束时间。两者特征不一致模型精度会立刻崩塌。我采用的常见做法是设计一个滑动时间窗口比如每 3 秒对过去 60 秒的流量做一次特征统计特征定义与训练时保持一致只是“流持续时间”被替换成“观测窗口内该流已经持续的时间”。具体架构是这样的模块功能技术选型流量采集从网卡镜像口或 pcap 文件读取流量Scapy / tcpdump特征计算按滑动窗口聚合为特征向量pandas collections 计数器模型推理加载训练好的模型文件joblib / pickle 加载决策输出返回预测结果超过阈值则告警FastAPI / Flask4.2 Scapy抓包与特征实时计算在线抓包用 Scapy 的sniff函数每捕获一个包就更新当前窗口内的计数器。注意sniff是阻塞式的要把抓包放在一个线程里跑主线程负责响应接口请求否则实时检测页面会卡死。from scapy.all import sniff, IP, TCP import threading import time from collections import defaultdict, deque import joblib model joblib.load(xgb_model.joblib) feature_scaler joblib.load(scaler.joblib) # 滑动窗口保存最近5分钟的数据包长度和时间戳 window_sec 300 packet_log deque(maxlen100000) flow_counter defaultdict(lambda: [0, 0, 0, None]) # count, bytes, syn_count, first_ts def packet_callback(pkt): now time.time() if pkt.haslayer(IP): length len(pkt) packet_log.append((now, length)) # 按五元组累计流量 proto TCP if pkt.haslayer(TCP) else UDP key (pkt[IP].src, pkt[IP].dst, pkt.sport if proto TCP else 0, pkt.dport if proto TCP else 0, proto) flow_counter[key][0] 1 flow_counter[key][1] length if proto TCP and pkt[TCP].flags 0x02: # SYN flag flow_counter[key][2] 1 # 每次到窗口边界就做推理 if len(packet_log) % 500 0: features compute_features(packet_log, flow_counter, now) if features: vec feature_scaler.transform([features]) prob model.predict_proba(vec)[0][1] if prob 0.8: print(f[ALERT] DDoS risk: {prob:.2f}) def start_sniffer(): sniff(prnpacket_callback, storeFalse) thread threading.Thread(targetstart_sniffer, daemonTrue) thread.start()这段代码的核心是deque(maxlen100000)它能自动丢弃超过 10 万条包的旧记录避免内存爆炸。窗口清理逻辑没有实时定时而是用包数触发特征计算这是一种折中方案优点是代码简单、演示稳定缺点是窗口边界不精确。compute_features函数需要自己实现计算的内容至少包括当前窗口总包数、平均包长、每秒包数、SYN 包占比、活跃流数、每条流的平均包数。这些特征必须和训练脚本里定义的特征顺序保持严格一致建议把特征提取抽成一个独立模块训练和部署共用同一份代码这是避免“离线 0.95在线 0.5”的关键。4.3 Flask/FastAPI封装模型加载与批量预测在线检测的演示效果取决于接口的交互体验。用 FastAPI 写一个 POST 接口接收前端或 curl 发来的流量特征返回预测概率。这样做的好处是把抓包和推理解耦抓包进程只负责算特征接口只负责预测后续接 Web 前端、接告警推送都很容易。from fastapi import FastAPI from pydantic import BaseModel import joblib import numpy as np app FastAPI(titleDDoS Detection API) model joblib.load(xgb_model.joblib) scaler joblib.load(scaler.joblib) class FeatureInput(BaseModel): features: list app.post(/predict) def predict(input_data: FeatureInput): vec np.array(input_data.features).reshape(1, -1) vec_scaled scaler.transform(vec) prob model.predict_proba(vec_scaled)[0][1] pred int(prob 0.8) return { prediction: pred, attack_probability: round(float(prob), 4) } # 启动uvicorn api_server:app --host 0.0.0.0 --port 8000注意接口接收的features顺序前端或抓包脚本提供的特征列表必须和训练时的feature_cols完全一致。我把训练脚本里特征列表输出成 JSON 存到文件里部署时直接读取就不会手写出错。阈值 0.8 不是固定不变的。如果误报率偏高调高到 0.9如果漏报明显降到 0.7。答辩时能说出“阈值是根据验证集上 F1 曲线最大值选取的”比“我拍脑袋选的 0.8”高级得多。5. 避坑指南DDoS检测毕设最常见的5个翻车点5.1 现象模型准确率 99%但线上演示一次都没报警原因离线训练时特征计算包含了整条流的统计信息。比如一个包还没到 SYN flood 的高潮期离线特征里已经被写入了整条流的持续时间和平均包长这些信息在真实抓包时根本拿不到。模型学会的是“看到完整结果再判断”而不是“根据实时趋势判断”。解决统一特征计算函数。离线特征提取和在线特征提取必须用同同一个模块唯一的差别是离线版读取整条 pcap在线版读取滑动窗口。做完这一步训练脚本的准确率会下降一点这才是真实水平。5.2 现象用CIC-IDS2017训练后效果好换成CIC-DDoS2019立刻崩盘原因两个数据集的背景流量不同CIC-IDS2017 是办公室网络环境CIC-DDoS2019 的实验环境更复杂特征分布差异很大。跨数据集泛化是检测系统的核心能力但大多数毕业论文只是单数据集验证。解决要么在论文里明确写清楚“模型仅适用于训练数据分布相近的网络环境”要么做一个简单的域验证用 CIC-IDS2017 的训练集建模、CIC-DDoS2019 的样本做测试看看指标掉多少。这个数据在答辩时是加分项。5.3 现象明明是随机抽样切分训练集和测试集F1 却高得不像话原因CIC 数据集里同一个源 IP 的连续攻击流量被随机分到了训练集和测试集两侧等于模型已经见过同一攻击流的片段测试时产生信息泄漏。学术上这叫做“分组泄漏”是 DDoS 检测论文里最容易出现的水分。解决按时间段切分。比如前 70% 时间段的流量作为训练集后 30% 作为测试集或者按源 IP 分桶后切分保证测试集里的 IP 从未在训练集出现过。后者更严格也更能体现模型的泛化能力。5.4 现象样本不均衡攻击样本只占 5%训练后模型几乎把所有流量都判为正常原因树模型默认以总体准确率为优化目标样本量小的攻击类被集体牺牲。有些学生看到 accuracy 96% 就觉得模型很好但没有看混淆矩阵和召回率。解决训练时用class_weightbalancedRandomForestXGBoost 用scale_pos_weight同时评估指标用 F1 值而不是 accuracy。更进一步可以做随机欠采样让正常流量和攻击流量比例接近 1:1 再训练这个方法在 DDoS 检测里很有效缺点是训练数据量变少需要配合交叉验证。5.5 现象在线抓包没跑几分钟内存占用就上来了原因sniff(storeFalse)没有存包但自己的packet_log和flow_counter一直在增长流计数器一旦超过内存限制就会拖垮系统。DDoS 流量每秒可以产生几十万条包每条流都要长期保存到窗口结束。解决给 flow_counter 加过期清理机制比如每 60 秒删除最后一次更新时间超过 300 秒的流。代码上用deque(maxlen...)限制包记录长度同时定期做流老化扫描。否则演示到后半段模型响应延迟会从毫秒级变成秒级直接被老师看穿。6. 验证与进阶让毕设从“能跑”变成“能答辩”6.1 用CIC-DDoS2019子集做交叉验证我训练模型的习惯是只取 CIC-DDoS2019 的一个子集比如只保留 UDP flood 和 DNS 反射攻击两类加上正常流量构成约 5 万条样本。子集比全量数据更快也更适合毕业论文的有限算力。交叉验证用 5 折分层 KFold模型差距在 0.1% 以内才说明稳定。一个更扎实的验证方法是在 UNSW-NB15 上做同样的二分类任务指标虽略差但趋势一致就能证明特征管线是通用的。6.2 可解释性用SHAP解释“为什么判它是攻击”训练完模型后我会额外做一个 SHAP 分析图。SHAP 值能显示每条样本里每个特征对最终预测的贡献方向。比如高包速率、高 SYN 比例会推高 DDoS 概率这个结论在论文里写出来比“模型准确率 98%”更有说服力因为老师能看出你真正理解了检测原理。SHAP 的用法是计算shap.TreeExplainer(xgb_model)然后用shap.summary_plot输出特征影响排序。注意样本量大时TreeExplainer会很慢随机取 1000 条样本即可。6.3 答辩前要准备的数据与图答辩材料里我推荐准备 4 张图1特征重要性 Top 20 柱状图2混淆矩阵热力图3训练集和测试集上的 PR 曲线4SHAP 摘要图。数据上准备 3 组单算法模型的性能指标、加上特征工程后的指标、模型在另一个数据集上的泛化指标。这组对照足够回答“为什么要用机器学习”“为什么选这个模型”“换环境还行不行”三个连环问。我的习惯是做完一个方案先把所有脚本统一放到一个目录里特征提取、训练、评估、在线检测四个文件之间用 JSON 传递特征列名保证任何人按顺序执行都能复现结果。这份工程化习惯比模型本身的调参更值钱因为我见过太多同学到最后答辩时连自己训练的模型参数都说不清楚。希望这份从数据集到避坑的完整路线能帮你少走弯路也希望你的毕设真正能落地成一份拿得出手的检测系统而不是停留在“跑了一个脚本”的阶段。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑