Win10下如何通过Python临时拦截发往指定IP的UDP数据包
Windows 10 下Python临时拦截指定目标IP出站UDP包方案
所有方案均要求脚本以管理员身份运行,否则会因权限不足完全失效。
方案1:调用系统防火墙实现拦截(零依赖、最稳定)
这个方案直接调用Windows自带的高级防火墙API添加临时出站拦截规则,拦截动作在内核层完成,不会漏包,不需要安装任何第三方工具或驱动,适合只需要按IP/端口维度拦截、不需要解析包内容的场景。
拦截结束后脚本会自动清理防火墙规则,不会在系统里残留配置。
import subprocess import atexit # 按需修改配置 TARGET_IP = "192.168.3.45" # 替换为你要拦截的目标IP BLOCK_RULE_NAME = "Python_Temp_UDP_Block" # 如果需要指定拦截端口,把下面的PORT配置改成对应端口,不需要就设为None TARGET_PORT = None def clean_firewall_rule(): """退出时自动删除临时防火墙规则""" subprocess.run( ["netsh", "advfirewall", "firewall", "delete", "rule", f"name={BLOCK_RULE_NAME}"], capture_output=True, shell=True ) def start_block(): """添加拦截规则""" rule_params = [ "netsh", "advfirewall", "firewall", "add", "rule", f"name={BLOCK_RULE_NAME}", "dir=out", "action=block", "protocol=UDP", f"remoteip={TARGET_IP}", "enable=yes" ] if TARGET_PORT: rule_params.append(f"remoteport={TARGET_PORT}") res = subprocess.run(rule_params, capture_output=True, text=True, shell=True) if res.returncode != 0: raise PermissionError("规则添加失败,请确认脚本以管理员身份运行") atexit.register(clean_firewall_rule) print(f"已开启拦截:所有发往{TARGET_IP}的UDP出站包将被丢弃,按Ctrl+C停止拦截") if __name__ == "__main__": try: start_block() while True: # 这里可以插入你的业务逻辑,比如满足特定条件后break结束拦截 input() except KeyboardInterrupt: pass finally: clean_firewall_rule() print("拦截已停止,防火墙规则已清理")
方案2:基于WinDivert实现自定义规则拦截(支持包内容解析)
如果你需要根据UDP包的载荷内容、包特征做细粒度拦截(比如只拦截包含特定字符串的包,其余正常放行),可以用pydivert库封装的WinDivert驱动实现用户态透明拦截,支持拦截、修改、放行任意匹配的网络包。
先安装依赖:pip install pydivert
示例代码:
import pydivert # 按需修改配置 TARGET_IP = "192.168.3.45" # 替换为目标IP TARGET_PORT = None # 需要指定端口就填对应数字,否则留None def start_custom_block(): # 构造过滤规则,语法和Wireshark过滤规则接近 filter_rule = f"udp and ip.DstAddr == {TARGET_IP}" if TARGET_PORT: filter_rule += f" and udp.DstPort == {TARGET_PORT}" try: with pydivert.WinDivert(filter_rule) as handle: print(f"自定义拦截已开启,将检查所有发往{TARGET_IP}的UDP包,按Ctrl+C停止") for packet in handle: # 在这里写你的自定义拦截逻辑 # 示例:拦截payload包含b"forbid"关键字的包,其余放行 if b"forbid" in packet.payload: print(f"拦截到违规包,长度{len(packet.payload)}字节,已丢弃") # 不调用send方法就是直接丢弃包 continue # 不符合拦截条件的包正常放行 handle.send(packet) except RuntimeError: raise PermissionError("驱动加载失败,请确认脚本以管理员身份运行,且安全软件未拦截驱动加载") if __name__ == "__main__": try: start_custom_block() except KeyboardInterrupt: print("\n拦截已停止")
这个方案第一次运行时会自动释放对应系统版本的WinDivert驱动到临时目录,部分安全软件可能弹出驱动加载提示,选择允许即可正常使用。
避坑说明
- 不要尝试用原始套接字、Scapy默认嗅探模式实现拦截:这两种方式只能在包已经发出到网卡后抓到副本,无法阻止包发送,本质是“抓包”不是“拦截”。
- 如果只需要临时拦截固定IP的UDP流量优先选方案1,稳定性最高,不会被安全软件误报,性能损耗几乎为0。
- 规则配置尽量收窄到具体端口,不要无差别拦截所有发往目标IP的流量,避免影响其他正常业务。
内容的提问来源于stack exchange,提问作者Spring93
相关产品推荐
相关产品推荐

