简易网络嗅探器编程实践

本文是 NIS3364 计算机通信网络课程设计的实验报告,实验内容为基于 Python 编写一款简易的网络嗅探器。文章详细介绍了项目的背景、技术选型、核心功能实现、测试验证以及项目总结与展望,旨在记录和分享网络嗅探器开发的全过程和心得体会。

网络嗅探简介

网络嗅探(Network Sniffing)是一种监视网络流量的技术,通过捕获网络中的数据包并进行分析,以了解网络通信情况。它可以帮助网络管理员诊断网络问题、检测网络攻击和优化网络性能。网络嗅探器工作在 OSI 模型的数据链路层,通过将网络接口设置为混杂模式(Promiscuous Mode),可以捕获经过该接口的所有数据包,而不仅仅是发送给自身的数据包。捕获到的数据包会被按照不同的协议进行解析,提取出源地址、目的地址、协议类型、数据内容等信息。

网络嗅探作为网络分析的核心技术,能够实时捕获网络中的数据包并进行解析,其应用场景十分广泛:

  • 网络故障排查:快速定位连接异常、协议错误等问题
  • 网络安全监控:检测 ARP 欺骗、端口扫描等恶意攻击行为
  • 性能优化分析:统计带宽使用情况,合理分配网络资源
  • 协议学习实践:直观观察 TCP、UDP 等协议的数据包结构

市面上的专业嗅探工具如 Wireshark 功能强大但过于复杂,对于协议学习和简单网络分析场景来说门槛较高。因此,我希望开发一款轻量、易用且核心功能完备的嗅探工具,既满足课程实践要求,又能为网络学习提供实用助力。

项目基本信息

核心技术栈

  • 开发语言:Python 3.10+(兼顾易用性和生态完整性)
  • 核心库:Scapy(数据包捕获与解析的核心工具,支持多协议处理)
  • 图形界面:Tkinter(Python标准库,轻量化且跨平台)
  • 辅助库:psutil(获取系统网络接口信息)
  • 文件格式:PCAP(行业标准的数据包存储格式,便于兼容其他分析工具)

项目结构设计

采用模块化设计思想,将项目拆分为三大核心模块,确保代码的可维护性和扩展性:

1
2
3
4
5
6
7
8
9
sniffer/
├── src/                    # 源代码目录
│   ├── main.py             # 程序入口,负责界面初始化和权限检查
│   ├── sniffer.py          # 核心模块,实现数据包捕获和状态控制
│   └── process_packet.py   # 数据包处理模块,负责协议解析和分片重组
├── test/                   # 测试脚本目录
├── ico/                    # 图标资源
├── requirements.txt        # 依赖配置文件
└── README.md               # 项目说明文档

项目地址

Github-NIS3364 Network Sniffer

网络嗅探器示意图

核心功能实现

网络嗅探器数据流示意图

基础功能:数据包捕获与网卡选择

嗅探器的核心是捕获网络数据包,这一步需要解决两个关键问题:

  • 网络接口适配:通过 psutil 库自动识别系统中的所有网卡,用户可在图形界面中选择监听对象
  • 权限控制:Windows 系统需要管理员权限,Linux/Mac 需要 root 权限,否则无法开启混杂模式
  • 捕获机制:利用 Scapy 的 sniff() 函数实现实时捕获,支持指定网卡、过滤条件和混杂模式开关

嗅探功能关键代码片段(sniffer.py):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def _sniff_packets(self, interface: str, protocol_filter: str):
    """数据包嗅探函数"""
    def packet_callback(packet):
        if not self.is_sniffing:
            return False
        self._process_packet(packet)

    # 构建协议过滤表达式
    if protocol_filter != "全部":
        if protocol_filter == "IPv4":
            filter_expr = "ip"
        elif protocol_filter == "IPv6":
            filter_expr = "ip6"
        else:
            filter_expr = protocol_filter.lower()
    try:
        scapy.sniff(iface=interface, prn=packet_callback, store=False,
                   stop_filter=lambda _: not self.is_sniffing,
                   filter=filter_expr, promisc=self.is_promiscuous)
    except Exception as e:
        self.root.after(0, lambda: messagebox.showerror("错误", f"嗅探失败: {str(e)}"))
        self.root.after(0, self._pause_sniffing)

核心能力:多协议解析与数据提取

捕获到的数据包需要经过解析才能提取有用信息,项目支持多种常见网络协议的解析,包括 TCP、UDP、ICMP、IPv4、IPv6、ARP 等常见网络协议,解析过程遵循 OSI 模型分层原则:

  • 数据链路层:提取 MAC 地址、接口信息
  • 网络层:解析 IP 地址、TTL、协议类型、分片标识
  • 传输层:提取端口号、序列号、确认号
  • 应用层:提取原始数据,支持十六进制/ASCII/UTF-8 多格式展示

以 IP 协议解析为例(process_packet.py):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def process_ip(packet: scapy.Packet, packet_info: Dict[str, Any]):
    if IP not in packet:
        return
    ip_packet = packet[IP]
    # 协议编号映射
    IP_proto_names = {1: "ICMP", 6: "TCP", 17: "UDP"}
    IP_proto_name = IP_proto_names.get(ip_packet.proto, f"Protocol {ip_packet.proto}")

    # 分片判断
    is_fragment = (not ip_packet.flags.DF) and (ip_packet.flags.MF or ip_packet.frag > 0)
    if is_fragment:
        packet_info["is_fragment"] = "1"

    # 提取核心信息
    packet_info["protocol"] = "IP"
    packet_info["src"] = ip_packet.src
    packet_info["dst"] = ip_packet.dst
    packet_info["detail"] += f"=== IPv4 层 ===\n"
    packet_info["detail"] += f"版本: {ip_packet.version}\n"
    packet_info["detail"] += f"头部长度: {ip_packet.ihl * 4} 字节\n"
    packet_info["detail"] += f"服务类型: {ip_packet.tos}\n"
    packet_info["detail"] += f"数据包总长度: {ip_packet.len} 字节\n"
    packet_info["detail"] += f"数据包标识: {ip_packet.id}\n"

    # 提取应用层数据
    if packet.haslayer(scapy.Raw):
        packet_info["data"] = packet[scapy.Raw].load

高级功能:分片重组与 PCAP 文件处理

IP 分片重组

当数据包超过 MTU(最大传输单元)时会被分片传输,重组功能能将这些分片还原为完整数据包:

  • 基于 IP ID、源 IP、目的 IP 和协议进行分片分组
  • 按偏移量排序分片,检查分片完整性
  • 支持重组后的数据预览和导出

分片重组关键代码片段(process_packet.py):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def reassemble_packet(Sniffer):
    """重组分片数据包"""
    # 获取当前选中的 IP 数据包信息,收集具有相同 IP ID、源 IP、目的 IP 和协议的所有分片及其对应的 packet_info 加入 fragments_with_info,并根据偏移量对其进行排序

    # 尝试重组数据包
    try:
        reassembled_data = b""
        for _, fragment, _, packet_info in fragments_with_info:
            # 优先使用 packet_info 中已解析的数据
            if packet_info["data"]:
                fragment_data = packet_info["data"]
            else:
                # 如果没有预解析数据,直接从 IP 包中提取载荷
                ip_header_length = fragment.ihl * 4
                fragment_data = bytes(fragment)[ip_header_length:]
            # 将当前分片数据添加到重组数据中
            reassembled_data += fragment_data

            # 检查分片完整性、从偏移量 0 开始的连续性、中间分片的连续性、是否有最后一个分片(没有 MF 标志)

        reassembled_detail = "=== 重组结果 ===\n"
        reassembled_detail += f"IP ID(数据报标识): {ip_id}\n"
        reassembled_detail += f"源 IP: {src_ip}\n"
        reassembled_detail += f"目的 IP: {dst_ip}\n"
        reassembled_detail += f"协议: {proto}\n"
        reassembled_detail += f"数据长度: {max_offset} 字节\n"
        reassembled_detail += f"是否完整: {'是' if is_complete else '否'}\n"
        reassembled_detail += f"缺失分片: {', '.join(missing_fragments) if not is_complete else '无'}\n\n"
        # 其余详细信息
        return reassembled_detail, reassembled_data

    except Exception as e:
        messagebox.showerror("重组错误", f"重组过程中发生错误: {str(e)}")
        return None, None

PCAP 文件兼容

支持将捕获的数据包保存为 PCAP 格式,也可加载已有的 PCAP 文件进行离线分析,方便后续复盘和分享:

1
2
3
4
5
6
7
8
def save_to_pcap(self):
    try:
        file_path = filedialog.asksaveasfilename(defaultextension=".pcap", filetypes=[("PCAP Files", "*.pcap")])
        if file_path:
            wrpcap(file_path, self.packets_to_save)
            messagebox.showinfo("成功", f"数据包已保存到{file_path}")
    except Exception as e:
        messagebox.showerror("错误", f"保存失败: {str(e)}")

交互体验:图形界面设计

采用 Tkinter 构建直观的图形界面,主要分为五大功能区域:

  • 网卡选择区:下拉列表展示所有可用网络接口
  • 过滤配置区:支持协议类型、IP 地址、端口号过滤
  • 捕获控制区:开始/暂停/清空等操作按钮,支持混杂模式开关
  • 数据包列表区:展示捕获到的数据包基本信息(时间、源 IP、目的 IP、协议、长度)
  • 详情展示区:左侧显示分层协议信息,右侧支持多格式数据查看
图形界面示例

功能测试与验证

为确保工具的稳定性和准确性,进行了多场景测试:

  1. 分片重组测试:发送长报文分片,成功重组并还原原始内容
  2. 文件传输测试:捕获 PNG 图片传输数据包,重组后通过脚本还原图片
  3. Ping 测试:分别测试 IPv4 和 IPv6 的 ICMP 协议解析,正常识别回显请求和响应
  4. 多协议测试:验证 TCP、UDP、ARP 等协议的解析能力,均能正确提取关键信息

测试结果表明,工具能有效捕获和分析网络数据包,满足基础网络监控和故障排查需求。

Ping IPv4 测试结果

项目总结与展望

项目总结

本项目成功实现了一款基于 Python 的简易网络嗅探器,具备数据包捕获、多协议解析、分片重组和 PCAP 文件处理等核心功能。通过模块化设计和图形界面交互,提升了工具的可用性和扩展性。测试结果验证了工具在多种网络场景下的稳定性和准确性,能够满足基本的网络监控和分析需求。

未来展望

由于时间和技术水平限制,项目仍有不少可优化之处,如若后续有更多时间,我会考虑从以下方面对项目进行进一步的优化与改进,实现一个更先进、更完善的网络嗅探器。

  1. 协议支持:目前主要支持传输层和网络层协议,后续可增加 HTTP、FTP、DNS 等应用层协议解析
  2. 性能优化:处理大量数据包时界面可能卡顿,需优化数据处理和界面刷新机制
  3. 分析能力:缺乏流量统计图表、异常检测等高级分析功能
  4. 跨平台兼容:在不同操作系统上的适配仍需完善

学习收获

通过本项目的开发,深入理解了网络协议的工作原理和数据包结构,掌握了网络嗅探的核心技术。同时,在项目开发过程中,也锻炼了问题分析和解决能力,学会了如何将复杂的功能分解为模块化的组件,提高代码的可维护性和可扩展性。

这次编程实践也让我切身体会到人工智能的发展迅速与实用价值。借助多模型 Agent 协作,从项目框架搭建、代码调试到 UI 界面迭代与文档生成,AI 工具有效降低了开发门槛、提升了问题解决效率,让我能够更聚焦于核心功能的逻辑实现与性能优化。这种人机协同的开发模式不仅是技术实践的助力,更启发了我对未来软件开发流程的思考——合理运用 AI 工具赋能编程工作,既能弥补个体经验的局限,也能为创新实践注入更多可能性,这将成为我后续学习与开发中持续探索的方向。

项目报告


简易网络嗅探器编程实践
https://youyeyejie.github.io/_posts/简易网络嗅探器编程实践/
作者
youyeyejie
发布于
2025年12月4日
更新于
2026年1月23日