Python扫描局域网存活设备仅返回本机与路由器IP问题咨询
局域网存活设备扫描仅返回本机与路由器IP的解决方案
问题核心原因
你现有代码仅能扫到本机和路由器,本质是扫描逻辑的问题:
- 你使用的ICMP ping扫描属于三层协议,绝大多数手机、智能IoT设备、开启默认防火墙的Windows主机都会禁止ICMP入站回显,不会响应ping包,自然会被判定为不在线
- 单线程扫描+超时时间设置过短,部分设备响应延迟稍高就会被漏判
- 部分实现的IP网段计算逻辑有误,没有覆盖实际的设备地址范围
同局域网内设备通信依赖二层ARP协议,只要设备在线、和你在同一广播域、未开启AP隔离,就一定会回应ARP请求,不存在防火墙拦截ARP的情况(拦截后设备无法正常联网),用ARP扫描的准确率远高于单纯ping扫描。
你提供的原代码参考


可直接运行的修复实现
依赖安装
先安装scapy库用于构造二层数据包:pip install scapy
完整扫描代码
from scapy.all import ARP, Ether, srp import socket import ipaddress def get_local_subnet(): """自动获取本机出口IP,计算同/24网段扫描范围""" sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: # 无需真实连接公网,仅用于获取本机正在使用的网卡IP sock.connect(("114.114.114.114", 80)) local_ip = sock.getsockname()[0] finally: sock.close() # 若你的网络使用非/24掩码,可自行修改此处的前缀长度 return str(ipaddress.ip_network(f"{local_ip}/24", strict=False)) def scan_alive_devices(subnet: str): """发送ARP广播包扫描网段内所有存活设备""" # 构造二层广播ARP请求包 arp_req = ARP(pdst=subnet) broadcast_ether = Ether(dst="ff:ff:ff:ff:ff:ff") packet = broadcast_ether / arp_req # 发送数据包,等待3秒接收响应,关闭冗余日志 resp = srp(packet, timeout=3, verbose=0)[0] device_list = [] for _, recv_pkg in resp: device_list.append({ "ip": recv_pkg.psrc, "mac": recv_pkg.hwsrc }) return device_list if __name__ == "__main__": target_subnet = get_local_subnet() print(f"当前扫描网段:{target_subnet}") devices = scan_alive_devices(target_subnet) print(f"扫描完成,共发现{len(devices)}台在线设备:") print("-" * 50) print(f"{'IP地址':<18}{'MAC地址'}") print("-" * 50) for dev in devices: print(f"{dev['ip']:<18}{dev['mac']}")
运行注意事项
- Windows系统下需要右键以管理员身份启动终端/IDE再运行脚本,否则scapy无权限发送原始二层数据包
- 若路由器开启了AP隔离功能,广播包无法到达其他客户端,任何扫描方式都无法获取其他设备信息,需要先关闭路由器的AP隔离配置
- 如果存在极个别漏扫的设备,可以在ARP扫描基础上增加多线程常见端口探测(探测80、443、22、3389、8080等常用服务端口),只要任意端口开放即可判定设备在线,进一步提升扫描准确率
内容的提问来源于stack exchange,提问作者Esra Issam
相关产品推荐
相关产品推荐

