如何解决pyshark抓取DHCP包时复用前包缺失字段存储值的问题
修复方案
核心修改点
- 每次处理新报文前清空字段存储容器,彻底避免复用旧报文的字段值
- 新增必填字段完整性校验,只有当前报文集齐所有需要的字段才执行统计、打印逻辑,字段不全直接跳过
- 修复原代码中
already_seen_mac_ips类型声明错误(原代码声明为字典却调用列表的append方法) - 修正DHCP域名字段取值的语法错误
修复后完整代码
import pyshark from collections import Counter # 配置抓取参数 capture = pyshark.LiveCapture(interface='wlo2', bpf_filter='udp port 67') capture.sniff_continuously(packet_count=15) # 定义必填字段列表,后续新增需要的字段直接在这里加即可 REQUIRED_FIELDS = ['mac', 'vendor', 'h_name', 'ip', 'sub_mask', 'server_ip', 'domain_name', 'dns'] already_seen_mac_ips = set() count = Counter() for packet in capture: # 每次处理新报文都初始化空字典,完全不复用旧报文的字段值 fields = {} try: # 优先取mac地址,这个是DHCP报文必带字段 fields['mac'] = packet.dhcp.hw_mac_addr # 逐个赋值可选字段 fields['vendor'] = packet.dhcp.option_vendor_class_id fields['h_name'] = packet.dhcp.option_hostname fields['ip'] = packet.dhcp.option_requested_ip_address fields['sub_mask'] = packet.dhcp.option_subnet_mask fields['server_ip'] = packet.dhcp.option_dhcp_server_id # 修正原代码的取值路径错误 fields['domain_name'] = packet.dhcp.option_domain_name fields['dns'] = packet.dhcp.option_domain_name_server except AttributeError: # 有任何字段缺失直接跳过本次报文,不保留任何本次的字段值 continue # 校验所有必填字段是否都成功取值,缺一个就跳过 if not all(k in fields for k in REQUIRED_FIELDS): continue # 走到这里说明本次报文所有字段齐全,执行统计和打印逻辑 count_key = (fields['mac'], fields['ip'], fields['h_name']) count.update([count_key]) mac_ip = (fields['mac'], fields['ip']) if mac_ip not in already_seen_mac_ips: print( packet.sniff_time, count[count_key], fields['mac'], fields['ip'], fields['h_name'], fields['vendor'] ) already_seen_mac_ips.add(mac_ip)
逻辑说明
- 每次新报文进入都生成全新的
fields字典,旧报文的字段值完全不会被带到下一次处理 - 只要有一个必填字段缺失,就直接跳过本次报文的所有后续处理,不会出现部分字段用旧值的情况
- 只有当前报文集齐了所有指定的必填字段,才会执行计数、去重判断、打印操作,完全符合需求
内容的提问来源于stack exchange,提问作者roXx
相关产品推荐
相关产品推荐

