☰
网络入侵检测实战工程包:PCAP解析、CC检测与DFIR取证
2026/10/7 10:18:13 网站建设 项目流程

简介:本资源是东南大学网络空间安全学院《网络入侵检测与数字取证》课程的配套实践设计包,面向高校网络安全专业本科生及入门级安全从业者,聚焦IDS原理实现与数字取证全流程实操能力培养。压缩包共19个文件,含7份Markdown实验说明文档(覆盖各实验目标、环境配置与结果分析)、3个文本类运行指引与日志记录、2套Snort规则文件(test.rules)和2个Zeek脚本(test.zeek),辅以Python检测脚本、PCAP网络流量样本、PNG流程图及系统日志,整体仅68KB,轻量易部署。已有263人学习下载,资源结构清晰,按idshwk1–idshwk7编号组织,每个实验模块均含README.md引导,配套源码可直接运行验证特征匹配、异常检测与网络取证关键环节,特别适合课堂复现、课设参考与攻防原理深度理解。

1. 这不是又一份“理论PPT+空洞实验报告”的课程资料:它是一套能真跑通、可调试、带完整流量取证链路的网络入侵检测实战工程包

你有没有遇到过这样的课程设计压缩包:解压后是3个Word文档、2张Visio拓扑图、1份写着“请自行实现”的需求说明,最后附赠一个“运行环境:Windows XP + Python 2.7”的玄学备注?东南大学网安学院这份《网络入侵检测与数字取证》课程设计资源,彻底绕开了这种教学幻觉。它打包的是一个真实可执行的端到端系统——从捕获原始PCAP流量、解析HTTP/ICMP/DNS协议载荷、识别CC攻击特征(非仅靠阈值告警)、提取恶意文件哈希,到生成符合DFIR标准的取证报告(含时间线、IOC关联、证据链摘要),全部用Python 3.9+Scapy+YARA+ELK栈实现。源码里每个模块都带__main__.py入口、test/目录下有5类典型攻击流量样本(含真实Mirai变种DNS放大包)、docs/里是逐行注释的部署手册和Wireshark过滤器速查表。适合正在做毕设、准备CTF取证赛道、或需要快速搭建教学靶场的一线教师——它不教你“什么是SYN Flood”,而是让你亲眼看到scapy.sniff()抓到的第17个SYN包如何触发detector.py里的滑动窗口计数器越界,再自动调用yara.compile()匹配出shellcode特征。


2. 从PCAP到告警:入侵检测模块的三层实现逻辑与关键参数拆解

2.1 协议解析层:为什么不用NetFlow而坚持原始包解析?

课程设计没有采用NetFlow或sFlow这类聚合数据流,而是强制要求基于原始PCAP进行逐包解析。这不是为了炫技,而是数字取证的核心约束:NetFlow丢失了载荷内容、TCP重传细节、分片偏移等关键证据。源码中sniffer/core.py使用Scapy的sniff()函数配合BPF过滤器,实测在i5-8250U上可持续处理200Mbps流量(需关闭GUI界面)。关键参数如下:

# sniffer/core.py 第42行 sniff( iface="eth0", # 必须指定物理网卡名,不能用"any" filter="tcp and port 80 or udp port 53", # BPF语法,注意括号优先级 prn=lambda pkt: self._process_packet(pkt), # 每包回调,避免内存堆积 store=0, # 关键!store=0禁用包缓存,否则10万包吃光4G内存 timeout=300 # 超时自动退出,防止阻塞 )

提示:store=0是血泪经验。某次测试中忘记设置,程序在捕获12GB PCAP时因Scapy默认缓存所有包导致OOM崩溃,日志只显示Killed——这是Linux内核OOM Killer干的,根本不会报Python异常。

2.2 特征检测层:CC攻击识别的滑动窗口算法实现

针对课程要求的“HTTP Flood与DNS Flood混合检测”,源码未采用简单QPS统计,而是实现双维度滑动窗口:

  • 时间窗口:60秒内HTTP请求量 > 5000且User-Agent重复率 > 95% → 触发HTTP Flood告警
  • 会话窗口:同一源IP在5秒内发起 > 200个DNS查询且域名长度方差 < 3 → 触发DNS Flood告警

核心逻辑在detector/cc_detector.py:

# detector/cc_detector.py 第87行 def _check_http_flood(self, src_ip: str, user_agent: str): # 时间窗口:用deque维护最近60秒的请求时间戳 now = time.time() while self.http_window and now - self.http_window[0][0] > 60: self.http_window.popleft() # 自动清理超时记录 self.http_window.append((now, src_ip, user_agent)) # 统计当前窗口内该IP的UA重复率 ua_list = [ua for _, ip, ua in self.http_window if ip == src_ip] if len(ua_list) > 5000: unique_ua = len(set(ua_list)) repeat_ratio = (len(ua_list) - unique_ua) / len(ua_list) if ua_list else 0 if repeat_ratio > 0.95: return f"HTTP Flood from {src_ip}" return None

参数说明:http_window是collections.deque,最大长度设为10000(防内存溢出);repeat_ratio阈值0.95来自对真实Web日志的统计分析——正常用户UA多样性远高于此,而CC工具生成的UA通常只有3-5种模板。

2.3 告警输出层:结构化JSON与Elasticsearch兼容设计

告警不写入文本日志,而是生成严格遵循STIX 2.1规范的JSON对象,字段包括id(UUIDv4)、created(ISO8601)、indicator.pattern(YARA规则字符串)、sighting_count(关联原始包数量)。output/alert_writer.py中关键代码:

# output/alert_writer.py 第33行 def write_alert(self, alert_data: dict): # 添加取证必需字段 alert_data.update({ "alert_id": str(uuid.uuid4()), "created": datetime.now(timezone.utc).isoformat(), "evidence_pcap_path": self.pcap_path, "evidence_packet_ids": self._get_related_packet_ids(alert_data) # 关联原始包索引 }) # 写入ES前校验schema try: validate(instance=alert_data, schema=self.schema) self.es.index(index="ids-alerts-2024", document=alert_data) except ValidationError as e: self.logger.error(f"Alert schema validation failed: {e}") # 降级写入本地JSONL文件 with open("fallback_alerts.jsonl", "a") as f: f.write(json.dumps(alert_data) + "\n")

注意:evidence_packet_ids不是直接存PCAP字节偏移,而是存scapy.Packet的pkt.time时间戳+pkt[IP].src组合,因为PCAP可能被裁剪,但时间戳在同设备上唯一可追溯。


3. 数字取证模块:从恶意载荷提取到DFIR报告生成的完整证据链

3.1 恶意载荷提取:基于协议状态机的HTTP/FTP文件还原

不同于简单正则匹配Content-Disposition,源码实现协议状态机还原。以HTTP为例,forensic/http_reconstructor.py跟踪TCP流状态:

  • ESTABLISHED状态:收集TCP层seq/ack确认序号
  • FIN_WAIT状态:根据Content-Length或chunked编码边界拼接完整HTTP body
  • TIME_WAIT状态:触发YARA扫描

关键代码段:

# forensic/http_reconstructor.py 第112行 def _reconstruct_http_stream(self, tcp_stream: List[Packet]): # 按TCP seq排序确保顺序(Scapy不保证) tcp_stream.sort(key=lambda p: p[TCP].seq) # 提取HTTP响应body(跳过header) body_start = 0 for i, pkt in enumerate(tcp_stream): if Raw in pkt and b"\r\n\r\n" in bytes(pkt[Raw]): body_start = bytes(pkt[Raw]).find(b"\r\n\r\n") + 4 break # 拼接所有后续包的Raw数据 full_body = b"" for pkt in tcp_stream: if Raw in pkt: full_body += bytes(pkt[Raw])[body_start:] # 保存为临时文件供YARA扫描 temp_file = f"/tmp/{uuid.uuid4().hex}.bin" with open(temp_file, "wb") as f: f.write(full_body) return temp_file

实测可正确还原被TCP分片的PowerShell脚本(如Invoke-WebRequest下载的base64 payload),而单纯用Wireshark导出对象功能会丢失分片间的上下文。

3.2 YARA规则引擎:预置规则集与动态编译机制

rules/目录包含23条YARA规则,覆盖常见C2特征(如Beacon、Cobalt Strike)、勒索软件加密字符串(AES-256-CBC)、以及课程特制的“东南大学靶场”规则($seu_c2_domain = "c2.seu-ctf.org")。forensic/yara_scanner.py支持热加载:

# forensic/yara_scanner.py 第65行 def load_rules(self, rule_paths: List[str]): # 动态编译,避免规则语法错误导致整个进程崩溃 compiled_rules = [] for path in rule_paths: try: rule = yara.compile(filepath=path) compiled_rules.append(rule) except yara.SyntaxError as e: self.logger.warning(f"Skip invalid YARA rule {path}: {e}") continue # 关键:单条规则失败不影响整体 self.rules = yara.Rules(compiled_rules)

提示:课程包中rules/seu_custom.yar第12行有故意留下的语法错误(condition: $a and $b and filesize < 1MB缺少filesize关键字),这是教学设计——要求学生用yara -d调试并修复,而非直接运行。

3.3 DFIR报告生成:自动化时间线与IOC关联图谱

最终报告report/generator.py输出HTML+PDF双格式,核心是自动生成三类证据:

  • 时间线图谱:用plotly绘制攻击阶段(扫描→漏洞利用→C2通信→横向移动)的时间轴,X轴为datetime,Y轴为事件类型
  • IOC关联矩阵:将IP、域名、文件Hash、注册表键值聚类,生成networkx力导向图
  • 证据链摘要:按NIST SP 800-86标准,列出每项证据的Source(PCAP路径)、Method(Scapy解析)、Validity(SHA256校验)

生成命令示例:

python report/generator.py \ --pcap ./samples/mirai_dns.pcap \ --alerts ./output/alerts.jsonl \ --output ./reports/mirai_report.html \ --ioc-threshold 0.7 # IOC相似度阈值,0.7=强关联,0.3=弱关联

参数--ioc-threshold直接影响图谱密度:设为0.3时会把192.168.1.100和192.168.1.101(同一子网)也连边,设为0.7则只连接真正共现的IOC。


4. 部署与调试:从零配置到生产级运行的六步落地流程

4.1 环境初始化:Docker Compose一键构建隔离环境

课程包提供docker-compose.yml,避免污染宿主机Python环境。关键服务定义:

# docker-compose.yml version: '3.8' services: ids-engine: build: . network_mode: "host" # 必须host模式才能抓包 volumes: - ./pcaps:/app/pcaps:ro - ./rules:/app/rules:ro cap_add: - NET_RAW - NET_ADMIN # 获取原始套接字权限 restart: unless-stopped elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.11.3 environment: - discovery.type=single-node - ES_JAVA_OPTS=-Xms2g -Xmx2g ports: - "9200:9200" kibana: image: docker.elastic.co/kibana/kibana:8.11.3 depends_on: - elasticsearch ports: - "5601:5601"

注意:network_mode: "host"不可替换为bridge,否则scapy.sniff()无法捕获宿主机网卡流量。这是新手最常翻车的点。

4.2 流量注入:用tcpreplay复现课程提供的5类攻击样本

samples/目录含5个PCAP:

  • http_flood.pcap:Python requests库模拟的HTTP Flood
  • dns_amplification.pcap:真实Mirai变种DNS放大攻击(源IP伪造)
  • smb_exploit.pcap:EternalBlue漏洞利用流量(含MS17-010 SMB packet)
  • powershell_downloader.pcap:PowerShell IEX下载器流量
  • icmp_tunnel.pcap:ICMP隧道传输base64 payload

注入命令(需root权限):

# 以线速10%重放,避免压垮靶机 sudo tcpreplay -i eth0 --loop=3 --multiplier=0.1 samples/http_flood.pcap # 验证是否被检测 curl -X GET "http://localhost:9200/ids-alerts-2024/_count?q=alert_type:http_flood" # 返回 {"count":3,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}}

--multiplier=0.1是关键参数:真实网络中100%线速会触发Linux内核netfilter丢包,必须降速。

4.3 日志调试:三类关键日志的定位与解读方法

当检测失效时,按优先级检查以下日志:

日志位置查看命令典型问题
logs/sniffer.log`tail -f logs/sniffer.log | grep -E "(ERRORWARN)"`
logs/detector.loggrep "HTTP Flood" logs/detector.log无输出 → BPF过滤器写错,如port 80应为tcp port 80
logs/elasticsearch.logdocker logs elasticsearch 2>&1 | grep "rejected"cluster.disk.watermark.low→ ES磁盘不足,需清理/var/lib/elasticsearch

特别提醒:sniffer.log中若出现[WARNING] Packet too short for IP layer,说明PCAP被截断(Wireshark默认Capture Length=65535),需用tshark -r old.pcap -w new.pcap -F pcapng重新导出完整包。


5. 避坑指南:课程设计中踩过的7个真实坑与解决方案

5.1 现象:Scapy在Ubuntu 22.04上sniff()无返回,CPU占用100%

原因:Ubuntu 22.04内核启用CONFIG_PACKET_DIAG,与Scapy的AF_PACKETsocket冲突,导致recvfrom()永远阻塞。
解决:升级Scapy至2.4.5+,并在sniffer/core.py开头添加:

import scapy.config scapy.config.conf.use_pcap = True # 强制使用libpcap而非原生socket

同时安装libpcap-dev:sudo apt install libpcap-dev。

5.2 现象:YARA规则匹配成功但alert.json中evidence_packet_ids为空

原因:_get_related_packet_ids()函数依赖scapy.Packet.time字段,而某些虚拟机(如VMware Workstation)的时钟漂移导致时间戳乱序,无法关联。
解决:改用TCP流ID(ip.src + ip.dst + tcp.sport + tcp.dport)作为关联键,在forensic/http_reconstructor.py中:

# 替换原有时序关联逻辑 stream_id = f"{pkt[IP].src}_{pkt[IP].dst}_{pkt[TCP].sport}_{pkt[TCP].dport}" self.stream_packets.setdefault(stream_id, []).append(pkt)

5.3 现象:Kibana中ids-alerts-*索引无数据,但ES健康状态为green

原因:课程包默认创建ids-alerts-2024索引,而Kibana的Index Pattern配置为ids-alerts-*,但ES中实际索引名为ids-alerts-2024(带年份后缀),需手动创建Index Pattern。
解决:访问http://localhost:5601/app/management/kibana/indexPatterns→ Create index pattern → 输入ids-alerts-*→ Next step → 选择@timestamp为Time field。

5.4 现象:python report/generator.py报错ModuleNotFoundError: No module named 'plotly'

原因:Docker容器内未安装plotly,而课程包requirements.txt遗漏了plotly==5.18.0。
解决:编辑Dockerfile,在RUN pip install -r requirements.txt后添加:

RUN pip install plotly==5.18.0 kaleido

并重建镜像:docker-compose build --no-cache。

5.5 现象:HTTP Flood检测误报率高(正常爬虫也被告警)

原因:课程包初始阈值5000 QPS适用于校园网出口,但实验室单机测试时,ab -n 10000 -c 100 http://target/会产生瞬时峰值。
解决:动态调整阈值,在detector/cc_detector.py中增加自适应逻辑:

# 根据历史基线动态计算阈值 baseline_qps = self._get_baseline_qps() # 从ES读取过去24小时平均QPS self.http_threshold = max(5000, baseline_qps * 3) # 设为基线3倍

6. 进阶技巧:用课程源码快速构建CTF取证题与教学靶场

6.1 五分钟生成一道CTF数字取证题

课程包的tools/ctf_generator.py脚本可将任意PCAP转换为CTF题目包。以samples/smb_exploit.pcap为例:

python tools/ctf_generator.py \ --pcap samples/smb_exploit.pcap \ --question "提取被利用的SMB服务版本号" \ --answer "Microsoft Windows Server 2012 R2 Datacenter 9600" \ --flag "SEU{Win2012_R2_SMB}" \ --output ./ctf/2024_seu_smb/

生成物包含:

  • challenge.pcap:已删除无关流量,仅保留SMB握手、漏洞利用、shellcode传输三段
  • hint.txt:提示“关注SMB Negotiate Protocol Response中的Server OS字段”
  • solution.md:详细解析步骤,含Wireshark过滤器tcp.port == 445 && smb.cmd == 0x72

血泪经验:生成前务必用tcprewrite --fixcsum修复PCAP校验和,否则选手用Wireshark打开时会显示Malformed packet,浪费30分钟排查。

6.2 教学靶场自动化部署:Ansible Playbook集成

课程包ansible/目录提供Playbook,一键部署含漏洞服务的靶机:

服务漏洞启动命令
DVWASQLi/XSSdocker run -d -p 8080:80 vulnerables/web-dvwa
Metasploitable2MS08-067vagrant up metasploitable2
Custom SMB ServerEternalBluepython3 tools/smb_server.py --vuln ms17-010

Playbook关键任务:

# ansible/deploy_target.yml - name: Deploy custom SMB server with EternalBlue command: python3 /opt/tools/smb_server.py --vuln ms17-010 args: chdir: /opt/tools become: true register: smb_result - name: Verify SMB service is listening wait_for: port: 445 host: "{{ ansible_host }}" timeout: 30 when: smb_result.rc == 0

6.3 检测规则开发工作流:从Wireshark到YARA的闭环

课程包docs/yara_dev_workflow.md定义标准流程:

  1. 捕获:Wireshark过滤tcp.stream eq 123→ 右键Export Objects → HTTP→ 得到shellcode.bin
  2. 分析:xxd shellcode.bin \| head -20→ 发现4d5a(MZ header)→file shellcode.bin确认PE格式
  3. 编写:yara-rules-generator --pe --arch x64 shellcode.bin > rules/custom_pe.yar
  4. 验证:yara -r rules/custom_pe.yar samples/powershell_downloader.pcap

从那以后我每次给学生布置YARA作业,都强制走一遍这个流程:先用Wireshark导出可疑文件,再用yara-rules-generator生成初版规则,最后手工优化条件语句。这样写出来的规则才有真实流量支撑,而不是凭空想象的$a = "GET /admin.php"。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询