
简介基于SDN的DDoS攻击检测与防御系统课程大作业源码包面向计算机科学、信息安全、数据科学与大数据、人工智能、通信及物联网等专业的学生和教师可作为毕业设计、课程设计或期末大作业的参考起点。项目代码已完成功能验证模块清晰便于在此基础上拓展和二次开发。包体共88个文件以71个Java源码文件为主辅以XML与YAML配置文件、Shell脚本、Markdown说明及TXT文档整体压缩包约62KB。目录结构涵盖src、test、main等分区能够帮助阅读者快速定位流量采集、攻击特征识别、策略下发等SDN安全检测与防御模块的逻辑实现。目前已有750人学习下载适合需要快速理解SDN环境下DDoS攻防机制或完成相关课程任务的人群。通过该源码包可以获得一套可运行的完整项目既能支撑课堂演示、初期立项也能作为深入网络安全的实战练习省去从零搭建的繁琐过程。1. 基于SDN的DDoS攻击检测与防御系统这套Java源码把课程设计最难的闭环补齐了期末课程设计选DDoS攻防方向很多人一开始就奔着「基于SDN的DDoS攻击检测与防御系统」去结果最难的不是写检测算法而是「检测到了却不知道怎么防御」——传统方案抓包、分析、手动封IP演示效果很单薄。这套源码用Java的Maven工程把检测和防御做成了闭环SDN控制器提供全局流量视图检测模块判定攻击防御模块自动下发OpenFlow流表阻断。它适合计算机、网络安全、通信、数据科学等专业的学生直接作为课程大作业或毕设演示也适合想快速入门SDN安全方向的从业者作为二次开发起点。我实际拆过这套工程先说结论值得下但环境版本匹配有点玄学这篇拆解把关键步骤和坑都摊开讲。2. 为什么用SDN做DDoS防护控制转发分离带来的三个实战优势2.1 传统DDoS防御在课程演示里的三个痛点做DDoS防御课程设计最常见的路线是在服务器上部署抓包工具比如tcpdump或Wireshark捕获流量后分析特征再手动用iptables封禁IP。这条路在原理上没错但放到答辩演示场景下有三个痛点。第一个痛点是流量采集不全。tcpdump只能看到本机网卡流量攻击如果打在拓扑里的其他主机上你得每台机器都部署采集脚本再把日志汇总到一起分析工程量大且容易漏。第二个痛点是防御动作滞后。iptables封IP属于事后手动操作攻击流量已经打进来一段时间了演示的时候评委问一句「检测到之后系统做了什么」你只能说「脚本会封禁IP」但整个过程看不到自动化的闭环。第三个痛点是环境复现困难。用物理交换机、路由器搭拓扑机房设备权限有限很多学生只有一台笔记本根本搭不出多主机、多交换机的攻击场景。SDN方案正好把这三个问题都绕过去了。Mininet用一台笔记本就能模拟出多交换机、多主机的网络拓扑SDN控制器的全局视图天然就是「全网流量视角」。检测到攻击后直接由控制器下发流表数据平面的交换机按规则丢弃或限速攻击流量检测和防御在同一个系统里闭环。演示时你能现场展示「流量进来→系统告警→流表下发→攻击被阻断」的完整过程这比贴一张抓包截图的说服力强太多了。提示如果之前没接触过SDN先记住一句话——控制器是大脑交换机是手脚。所有流量转发决策由控制器统一下发这就是「控制转发分离」。2.2 SDN检测架构控制器、交换机和检测器的三个协作角色这套系统的架构可以拆成三层来理解。数据平面由Open vSwitchOVS交换机组成Mininet负责在笔记本上虚拟出这些交换机和主机。OVS交换机只做一件事按照流表匹配流量并执行动作匹配不到就通过OpenFlow协议向控制器询问。控制平面是SDN控制器的职责控制器收集所有交换机的拓扑、端口统计、流表统计信息也负责把检测系统的防御策略转换成OpenFlow流表下发到指定交换机。检测与防御应用层是这套源码的核心。它定时通过REST接口从控制器拉取各交换机端口和流表的统计计数计算流量特征包速率、字节速率、目的IP熵等一旦超过阈值就进入攻击响应流程调用控制器的北向接口下发丢弃或限速流表。常见的开源控制器有ONOS、OpenDaylight、Ryu这套Java工程走的是REST API路线控制器本身不需要二次开发只需要开放北向接口。我拆这套工程的时候发现它的架构选择是比较聪明的没有把检测算法写进控制器内部而是做成独立Java服务。这样检测逻辑和控制器解耦换控制器品牌不用改检测代码只需要改北向接口适配层。如果你后续想换成Ryu也只需要重写一层REST客户端核心的检测算法和防御策略都能直接复用。2.3 检测算法怎么选速率阈值、流量熵与机器学习的取舍源码里真正决定「能不能检测到DDoS」的是特征提取和判定算法。市面上课程设计常用的有三类思路。第一类是速率阈值检测单位时间内的包数或字节数超过基线就告警。实现最简单对SYN Flood、UDP Flood这类高流量攻击很有效但基线需要手动定网络波动大时容易误报。第二类是流量熵检测统计目的IP地址分布的信息熵。正常流量下目的IP分散熵值高DDoS攻击发生时大量流量涌向少数几个目标熵值显著下降。这个思路能抓出低速慢速攻击比纯阈值更抗噪计算量也不大课程设计里属于「性价比最高」的方案。第三类是机器学习分类用决策树、随机森林、SVM等模型对流量特征做分类。听起来高大上但需要标签数据训练特征工程做不好模型效果还不如阈值。课程设计时间有限不建议上来就上机器学习除非你本身就打算走算法创新方向。这套源码的检测模块里阈值检测和熵检测是同时跑的两个维度交叉确认再触发防御。我建议拿到源码后先不改算法把默认阈值跑通理解了数据流再按自己的网络环境调参。算法思路实现成本抗误报能力答辩说服力推荐度速率阈值低弱中先用它跑通闭环流量熵中中较强强烈推荐机器学习高依赖数据强有余力再上3. 源码工程拆解Maven根模块、service模块与核心数据流3.1 工程目录结构与pom.xml先看懂两个模块的分工压缩包解开之后目录结构是典型的Maven多模块布局。根目录一个pom.xml下面有service子模块它自己也带一个pom.xml源码主体在src/main/java测试代码在src/test/java。这种结构在课程设计里很常见根pom负责管理公共依赖和模块聚合service模块放业务逻辑。先看根pom.xml里最关键的依赖声明。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent groupIdcom.course/groupId artifactIdsdn-ddos-defense/artifactId packagingpom/packaging modules moduleservice/module /modules dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.apache.httpcomponents/groupId artifactIdhttpclient/artifactId version4.5.14/version /dependency dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId /dependency /dependencies这段依赖声明里具体版本号以你解压后的pom.xml为准这里给的是这个场景下最常用的搭配。Spring Boot 2.x是课程设计最常见的基座自带嵌入式Tomcat检测服务可以直接用Web方式对外提供REST接口也方便后期接可视化面板。依赖里最核心的是httpclient和jackson-databind两个httpclient负责向控制器发起HTTP请求比如拉取端口统计、下发流表jackson负责把控制器返回的JSON流量数据转成Java对象。看清这几个依赖整个工程的网络通信逻辑就明白了一半。3.2 流量采集模块从控制器拉取统计信息的实现流量采集是整个系统的数据入口。检测算法再花哨拿不到准确流量统计都是白搭。这个模块的核心工作是定时向控制器查询各交换机端口的统计把累计的包数、字节数存下来并在两个采样周期之间做差分得到实时速率。public class FlowStatsCollector { private static final String CONTROLLER_BASE_URL http://127.0.0.1:8181; private static final String STATS_URI /onos/v1/statistics/ports/; private final CloseableHttpClient httpClient HttpClients.createDefault(); private final ObjectMapper mapper new ObjectMapper(); public ListPortStat fetchPortStats(String deviceId) throws IOException { String url CONTROLLER_BASE_URL STATS_URI deviceId; HttpGet request new HttpGet(url); request.setHeader(Authorization, Basic java.util.Base64.getEncoder().encodeToString(onos:rocks.getBytes())); try (CloseableHttpResponse response httpClient.execute(request)) { String json EntityUtils.toString(response.getEntity()); JsonNode root mapper.readTree(json); JsonNode stats root.get(statistics); ListPortStat result new ArrayList(); stats.forEach(node - result.add(mapper.treeToValue(node, PortStat.class))); return result; } } }代码逻辑分三段第一段构造HTTP GET请求路径是控制器的北向REST接口这里以ONOS的端口统计接口为例第二段设置Basic Auth认证用户名密码按你部署控制器时配置的来改第三段解析JSON响应把每条端口的包数、字节数映射成PortStat对象。注意这里拿到的是累计计数不是瞬时速率。计算攻击特征时必须用当前采样值减去上一次采样的值再除以采样间隔才能得到每秒包数pps和每秒字节数Bps。很多同学直接拿累计值当速率用检测结果当然不准误报率飙升。3.3 检测判定模块阈值与熵双重判定的实现检测模块是这套系统的核心。源码里同时维护了速率阈值检测和目的IP熵检测两个维度。速率阈值部分逻辑很直接统计攻击窗口内收到的TCP SYN包速率或UDP包速率与基线速率相比超过设定倍数就标记为可疑。基线是系统启动后前几分钟正常流量的平均值。public class DdosDetector { private final double rateThresholdMultiplier 3.0; private final double entropyThreshold 0.6; public DetectionResult detect(FlowFeatureWindow window) { boolean rateAlert false; boolean entropyAlert false; // 维度一速率阈值当前速率超过基线3倍触发 if (window.getCurrentPps() window.getBaselinePps() * rateThresholdMultiplier) { rateAlert true; } // 维度二目的IP熵熵值低于0.6说明流量高度集中 if (window.getDestIpEntropy() entropyThreshold) { entropyAlert true; } // 两个维度至少命中一个且持续两个采样周期才判定攻击 if ((rateAlert || entropyAlert) window.getConsecutiveHits() 2) { return DetectionResult.attack(window.getAttackType()); } return DetectionResult.normal(); } }判定逻辑有两个值得抄的设计。第一是「双维度交叉」速率异常但熵正常可能是突发的正常大流量比如期末大家都在传大文件单看速率会误报加上熵维度后目的IP分布不集中就不轻易判攻击。第二是「连续命中两次才确认」网络流量天然有毛刺一次尖峰可能是脉冲连续两个采样周期都过阈值攻击的可信度就高多了。3.4 防御响应模块OpenFlow流表下发与限速实现检测判定攻击后防御模块开始工作。这套系统的防御动作分两级第一级是黑洞指令匹配攻击特征源IP、目的IP、协议端口的流量直接丢弃第二级是限速指令用OpenFlow Meter表把攻击流量限制到可容忍的带宽保证正常业务不受影响。课程设计答辩时评委经常追问「如何保证正常用户不受影响」所以限速逻辑的代码路径要捋清楚。public class DefenseResponder { private static final String FLOW_URI /onos/v1/flows/; private final CloseableHttpClient httpClient HttpClients.createDefault(); public void blockSourceIp(String deviceId, String sourceIp) throws IOException { String flowJson { \priority\: 40000, \timeout\: 0, \isPermanent\: true, \deviceId\: \ deviceId \, \treatment\: { \instructions\: [] }, \selector\: { \criteria\: [ { \type\: \IPV4_SRC\, \ip\: \ sourceIp \ } ] } }; HttpPost request new HttpPost(FLOW_URI deviceId); request.setEntity(new StringEntity(flowJson, ContentType.APPLICATION_JSON)); try (CloseableHttpResponse response httpClient.execute(request)) { if (response.getStatusLine().getStatusCode() ! 200) { throw new IOException(流表下发失败: response.getStatusLine()); } } } }这段代码展示的是按源IP阻断的思路。实际OpenFlow流表里selector可以组合多个匹配条件比如源IP加目的IP加TCP目的端口匹配更精确误杀范围更小。priority值必须设高因为SDN交换机里默认转发规则的优先级一般是低数值你的丢弃规则优先级不高于它流量还是会走默认转发路径。如果攻击伪造源IP只按源IP匹配很容易被绕过这也是后面避坑章节要展开的细节。注意下发丢弃流表是「堵」不是「疏」。正常业务和攻击流量如果同源同目的全丢会伤及无辜所以源码里保留了一版限速指令作为可选项攻击流量降速而不是全部丢弃业务连续性更好。4. 环境搭建与攻击复现Mininet拓扑、控制器与DDoS实测4.1 环境版本匹配JDK、Maven、控制器和Mininet怎么配拆这套工程时踩的第一个坑就是版本匹配。SDN生态的版本兼容性很微妙控制器版本、Mininet版本、OVS协议版本彼此之间都有依赖关系。下面是我验证过能跑通的组合直接照着配能少走弯路。组件版本建议说明JDK1.8 或 11Spring Boot 2.x对JDK8支持最好11也能跑Maven3.63.8以上对仓库下载更稳定控制器ONOS 2.x 或 OpenDaylight二选一源码默认走ONOS风格RESTMininet2.3.0自带OVS 2.x支持OpenFlow 1.3操作系统Ubuntu 18.04/20.04不建议Windows宿主直接跑MininetMininet官方支持LinuxWindows用户建议用VMware装Ubuntu虚拟机网络模式选桥接或NAT都行只要虚拟机能访问到控制器的北向端口。如果你手里有eve-ng这类网络模拟环境也可以用eve-ng拉ONOS镜像效果一样但配置复杂度更高课程设计不推荐优先走这条路。Java工程和控制器放在同一台机器上跑Mininet单独一台虚拟机中间用管理网络连通这样攻击实验时打流量产生的CPU开销不会拖垮控制器。4.2 启动流程控制器、检测服务、Mininet拓扑的顺序不能乱启动顺序是这套系统能不能正常工作的关键。三个组件的启动顺序如果错了交换机连不上控制器检测服务拉不到统计数据整个系统就是个黑匣子。# 第一步启动SDN控制器ONOS为例 cd ~/onos ./bin/onos-service server # 第二步等控制器完全启动检查北向REST接口是否可用 curl -u onos:rocks http://127.0.0.1:8181/onos/v1/statistics/ports # 第三步启动Java检测服务工程根目录 cd sdn-ddos-defense mvn clean package -DskipTests java -jar service/target/sdn-ddos-service.jar --controller.urlhttp://127.0.0.1:8181 # 第四步最后拉Mininet拓扑让交换机主动连接控制器 sudo mn --custom ~/sdn-ddos-defense/topology.py --topo mytopo \ --controllerremote,ip127.0.0.1,port6653 \ --switch ovs,protocolsOpenFlow13第一条命令把ONOS跑起来后不要急着启动后面的组件。控制器初始化需要一到两分钟第一次启动还会加载应用插件REST接口没就绪时检测服务会一直连不上。用第二条命令curl一下接口能返回JSON列表再继续往下走。Mininet的--controller参数指定了远程控制器的IP和端口6653是OpenFlow的默认监听端口。--switch ovs,protocolsOpenFlow13指定使用Open vSwitch并协商OpenFlow 1.3协议如果协议版本对不上交换机和控制器握手会失败这是SDN实验最常见的翻车点。4.3 模拟DDoS攻击用hping3和Scapy打流量看检测结果拓扑起来之后先验证正常流量确认基线稳定接着用攻击工具打流量看检测服务能不能在几秒内报警并下发防御规则。# 在Mininet的h1主机里向h2发起正常的HTTP请求 h1 wget -q -O /dev/null http://10.0.0.2/ # 模拟SYN Flood攻击高速率发送TCP SYN包 h1 hping3 -S -p 80 --flood 10.0.0.2 # 查看检测服务日志确认攻击告警和防御动作 tail -f /var/log/sdn-ddos-service/defense.loghping3的-S参数指定SYN包-p 80指定目的端口--flood表示尽最大速率发包。正常课程设计演示这个命令打出去三到五秒检测服务就应该在日志里打出攻击告警同时输出流表下发的记录。如果五分钟都没告警优先检查两件事第一检测服务的采样间隔是不是默认配置间隔太长会拖慢响应第二拉取的统计接口是否匹配实际控制器ONOS和OpenDaylight的REST路径不一样源码里默认按ONOS格式写的换控制器要改路径。用Scapy也能做类似效果适合后续扩展自定义攻击类型。下面这段脚本生成UDP Flood流量可以在Mininet里的h1主机跑from scapy.all import * import time # 目标主机IP包大小固定为1200字节源IP随机伪造 target_ip 10.0.0.2 packet IP(srcRandIP(), dsttarget_ip) / UDP(sportRandShort(), dport53) / Raw(loadbX*1200) # 控制发包速率每秒钟发送2000个UDP包 send(packet, count2000, inter1.0/2000, verbose0)脚本里RandIP随机生成源IPRandShort随机生成源端口目的是模拟真实攻击中常见的源地址伪造。inter参数控制发包间隔把它改小就是变相提高攻击速率方便你测试不同阈值下的检测响应时间。这个脚本跑起来后可以同时打开检测服务的监控接口观察pps和熵值的实时变化为后面的可视化进阶做准备。5. 避坑排查这套系统最常见的五个翻车现场5.1 现象Mininet里的交换机一直连不上控制器表现为mn命令行启动拓扑后控制器界面里看不到任何交换机上线检测服务也拉不到端口统计。原因基本是三点控制器IP配错、6653端口没监听、OpenFlow协议版本不匹配。其中协议版本不匹配最隐蔽——ONOS默认协商OpenFlow 1.3如果Mininet启动时不指定协议版本OVS会用默认版本去握手控制器直接拒绝。解决先用ovs-vsctl show查看交换机实际连接状态确认控制器地址再用netstat -tlnp | grep 6653确认控制器监听端口最后在Mininet启动参数里显式加上--switch ovs,protocolsOpenFlow13。如果仍然失败把控制器日志级别调到DEBUG看OpenFlow握手消息一般能定位到版本协商失败的记录。5.2 现象检测模块误报率极高正常流量也触发防御表现为仅仅跑了个wget下载文件检测服务就告警并下发阻断流表网络直接瘫痪。原因在于基线学习阶段没有采到正常流量特征。系统启动后检测服务立即开始学习基线如果你在启动后几秒内就开始测试基线的平均值接近0任何一点流量都超过阈值倍数。解决检测服务启动后先等三到五分钟期间跑一些正常流量让基线稳定。另外检查baseline窗口配置一般设置60到120秒采样窗口。还有一个常见误用是直接把阈值倍数调低来减小误报这会把真正的攻击漏掉正确做法是先保证基线准确再动判定参数。5.3 现象防御流表下发了但攻击流量照样通表现为日志里明确输出了流表下发成功但抓包或观察目标主机负载攻击流量仍然到达目标目标主机CPU被打满。原因是流表优先级不够。SDN交换机里如果存在优先级更高的转发规则你的丢弃规则优先级低流量会先命中转发规则直接放行。解决把防御规则的priority值调高到接近交换机支持的最大值比如65000。同时检查匹配字段是否精确有些实现只用源IP匹配攻击如果伪造源IP换一批源IP就绕过了。建议把目的IP、协议、目的端口都加进匹配条件让防御规则同时具备精确性和高优先级。5.4 现象Maven依赖下载缓慢或失败service模块编译报错表现为mvn package时长时间卡在下载插件或者提示某个依赖找不到工程编译失败。原因是Maven中央仓库访问不稳定Spring Boot和HTTPClient的依赖体积不小加上课程设计时间节点网络波动很容易超时。解决在Maven的settings.xml里配置阿里云镜像这是Maven工程通用操作配好后重新执行mvn clean package速度通常会提升一个量级。如果下载的依赖和源码pom.xml里声明的版本对不上检查Maven本地仓库是否残留了损坏的.lastUpdated文件删掉对应目录让它重新下载。5.5 现象防御之后系统恢复不了正常业务也一直被阻断表现为攻击停止后防御流表还留在交换机上后续正常流量持续被丢弃必须重启Mininet才能恢复。原因是流表没有设置过期时间也没有做防御撤销。很多课程设计演示到这里就翻车了——你挡住了攻击但也把正常用户挡在了门外。解决实现一个防御自愈逻辑检测服务每30秒检查一次攻击流量是否还在连续两个周期都正常就调用控制器删除之前下发的流表。这是第6章会展开说的进阶点也是这套系统从「能交差」到「能拿高分」的分水岭。要留意的是删除流表的接口和下发是配对关系ONOS里用DELETE请求带流表ID写代码时把下发的流表ID存下来否则撤销时找不到目标。6. 进阶把检测指标接进Grafana做实时可视化的答辩加分项6.1 暴露REST API把检测数据从黑匣子变成可读指标这套系统跑通之后检测服务的日志里已经能看到告警但答辩时不可能让评委盯着终端日志看。我习惯的做法是给Spring Boot工程加一个轻量的监控接口把当前窗口的流量特征实时吐出来。前面的检测器里正好有当前窗口的pps和熵值暴露成REST接口只需要一个Controller。RestController RequestMapping(/api/monitor) public class MonitorController { private final DdosDetector detector; public MonitorController(DdosDetector detector) { this.detector detector; } GetMapping(/stats) public MapString, Object stats() { MapString, Object result new HashMap(); result.put(pps, detector.getCurrentPps()); result.put(entropy, detector.getDestIpEntropy()); result.put(status, detector.getCurrentStatus()); result.put(blockedIps, detector.getBlockedIpCount()); return result; } }这个接口把检测器内部状态直接暴露出来字段含义和3.3节判定逻辑一一对应。加这个接口不影响现有检测流程只是多了一个读数据的口子后面接监控面板时不用再解析日志文件。6.2 用Grafana把指标画成折线攻击曲线一眼可见课程设计场景我不建议上Prometheus全家桶太重。直接用Grafana的JSON API数据源配置要点有四个数据源类型选JSON APIURL填检测服务地址加/api/monitor/stats查询类型用JSON Path把pps和entropy字段分别映射到两个面板刷新时间设在1到5秒之间面板类型选时间序列折线图。攻击发生时几秒内就能看到pps直线拉高、熵值跌到0.6以下的滑落曲线。实际演示时我会配两个面板上面放pps速率折线下面放目的IP熵值折线。实验流程是先跑正常流量看到熵值稳定在0.9以上再启动hping3曲线突变最后停止攻击展示防御系统撤销流表后曲线回落。整个过程连贯、有数据支撑视觉冲击力比解释原理强得多。从那以后我每次拿到新的SDN检测工程都会强制走一遍同样的流程先看pom和目录结构确认数据流再跑通正常流量基线最后才做攻击实验并且把可视化面板作为标配功能提前接上。这套源码本身已经帮你省了最核心的检测和防御闭环剩下这些锦上添花的部分值得花一个晚上加上。希望帮到你。本文还有配套的精品资源点击获取