Scapy嗅探STUN数据包时避免重复打印IP的优化方法求助
Omegle STUN数据包嗅探IP去重优化方案
核心改动为将原有的本地文件读写去重逻辑替换为内存集合存储,彻底解决原方案需要提前创建文件、仅能记录单个IP、读写效率低的问题,优化后可运行代码如下:
import sys import requests import json from scapy.all import * from rich.console import Console from rich.table import Table from rich import print # STUN协商固定标识字节 stunxor = ' 01 01 00 2C ' localip = str(sys.argv[1]) console = Console() # 存储已发现的IP,内存去重 seen_ips = set() def print_summary(pkt): try: hexpkt = hexstr(pkt, onlyhex=1) if stunxor in hexpkt: ip_addr = pkt[IP].src # 已见过的IP直接跳过 if ip_addr in seen_ips: return # 新IP加入集合 seen_ips.add(ip_addr) # 拉取IP地理位置 try: api_resp = requests.get(f"https://ipinfo.io/{ip_addr}/geo", timeout=5) api_resp.raise_for_status() api_data = api_resp.json() except Exception as e: print(f"IP信息获取失败:{e}") return # 渲染表格 console.clear() table = Table(title='Current user data') table.add_column("IP", style="cyan", no_wrap=True) table.add_column("Country", style="cyan", no_wrap=True) table.add_column("City", style="cyan", no_wrap=True) table.add_column("Subdivision", style="cyan", no_wrap=True) table.add_row( ip_addr, api_data.get('country', '未知'), api_data.get('city', '未知'), api_data.get('region', '未知') ) console.print(table, justify="center") except Exception as e: print(f"数据包处理失败:{e}") if __name__ == "__main__": try: filter_rule = f"src not {localip} and udp and host {localip}" sniff(filter=filter_rule, prn=print_summary, iface='Ethernet') except Exception as e: print(f"嗅探启动失败:{e}")
优化说明
- 新增全局
seen_ips集合存储所有已处理过的IP,判断IP是否重复的时间复杂度为O(1),远高于原有每次读取本地文件的效率 - 无需提前创建本地文件即可运行,避免文件不存在导致的启动报错
- 支持记录所有历史发现的IP,而非仅记录最近一个IP,完全避免重复打印同一IP的数据包
- 新增IP信息接口请求超时、异常兜底,使用
dict.get()方法获取字段,避免部分IP无对应地理位置字段时程序抛出异常 - 优化了代码结构,减少不必要的嵌套异常捕获,问题排查更清晰
如果需要程序重启后仍保留历史IP记录,可额外补充持久化逻辑:启动时从本地文件读取历史IP写入集合,新增IP时同步追加写入本地文件即可。
内容的提问来源于stack exchange,提问作者ANK Exposure
相关产品推荐
相关产品推荐

