scapy发送arp请求比ping更可靠,因iot设备等常禁ping但必须响应arp;需用srp()发广播arp包(如pdst="192.168.1.0/24"),解析received.psrc即可确认活跃ip。

用 scapy 发送 ARP 请求比 ping 更可靠
局域网扫描活跃 IP,ping 常常漏掉——很多设备(如手机、IoT 设备)默认禁 ping,但只要在线,ARP 层必须响应。用 scapy 构造广播 ARP 请求,直接问 “192.168.1.x 的 MAC 是多少?”,收到回复就说明该 IP 活跃。
实操建议:
- 先确认本机网卡和子网:运行
ipconfig(Windows)或ifconfig(macOS/Linux),找到 IPv4 地址和子网掩码,推导出网段(如192.168.1.0/24) - 安装依赖:
pip install scapy;Linux/macOS 可能需sudo权限才能发原始包 - 关键代码片段:
from scapy.all import ARP, srp arp = ARP(pdst="192.168.1.0/24") result = srp(arp, timeout=2, verbose=False)[0] for sent, received in result: print(received.psrc) - 别用
sr()(只发不收)或send()(无返回),必须用srp()(第二层发送+接收)
避免被防火墙/交换机限速或丢包
快速连续发 ARP 包容易触发交换机端口限速、被终端防火墙静默丢弃,导致漏扫。这不是代码 bug,是网络设备行为。
实操建议:
- 加
threading或concurrent.futures并行多个子网段(如/25),比单线程扫整个/24更稳 - 控制速率:在
srp()中加inter=0.1(每包间隔 100ms),或用timeout=1缩短等待时间 - 跳过已知保留地址:
pdst="192.168.1.1-254"比"192.168.1.0/24"少扫两个无效地址(.0 和 .255) - Windows 上若报错
socket.error: [Errno 10013] An attempt was made to access a socket...,说明没以管理员身份运行
Python 自带 subprocess 调用系统 ping 作为 fallback 方案
当目标设备禁 ARP(极少见)或你无法装 scapy 时,subprocess.run(["ping", "-n", "1", "-w", "500", ip]) 是兜底选择,但要处理平台差异。
实操建议:
- Windows 用
-n 1 -w 500,Linux/macOS 用-c 1 -W 1;统一写法推荐用platform.system()分支判断 - 别依赖
returncode == 0:某些系统下丢包但返回 0,应检查 stdout 是否含"TTL="(Windows)或"bytes from"(Linux) - 并发调用
ping易触发系统进程数限制,建议用ThreadPoolExecutor(max_workers=20)控制并发量 - 注意:
ping扫描比 ARP 慢 5–10 倍,且对 ICMP rate-limiting 敏感,仅作补充验证用
输出结果要区分“在线”“无响应”“超时”三类状态
单纯打印 IP 列表意义有限。真实运维中需要知道是设备关机、防火墙拦截,还是网络不可达。
实操建议:
- 对每个 IP 记录三种响应:
"alive"(ARP 回复 / ping 成功)、"filtered"(ARP 请求发出但无回复,可能防火墙拦截)、"unreachable"(ARP 请求都发不出,如网关不通) - 用
datetime.now().isoformat()打时间戳,方便对比多次扫描差异 - 导出为 CSV 时字段建议:IP、MAC(ARP 有)、响应延迟(ping 有)、探测方式、时间戳
- 别把
169.254.x.x(APIPA)或127.0.0.1当有效局域网地址混入结果
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











