You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python网络扫描器检测活跃主机时返回空列表的问题求助

Python网络扫描器检测活跃主机时返回空列表的问题求助

我最近在做一个网络扫描器项目,遇到了个头疼的问题:我写了两个脚本,target_network_input.py负责让用户输入目标网段,输出可用主机列表和总地址数;active_networks.py接收这个主机列表,通过ICMP、TCP、UDP、ARP四种方式探测活跃主机,最后把活跃的主机收集起来输出。但不管怎么测试,结果总是返回空列表,完全达不到预期效果,有没有大佬能帮我看看哪里出问题了?

我的代码如下:

target_network_input.py

#!/usr/local/bin/python3
import ipaddress
def process_network():
    n = input('Enter the target network range (e.g., 192.168.1.0/24):  ')
    try:
        net = ipaddress.IPv4Network(n, strict = False)
        net_list = list(net.hosts())
        net_num = net.num_addresses
        print(f'Usable hosts: {net_list}\n')
        print(f'Total number of addresses (including network and broadcast): {net_num}')
        return net_list
    except ValueError:
        print('Invalid IP network range')

if __name__ == '__main__':
    #Standalone execution logic(if needed)
    print('This script is used to process network ranges')
    process_network()

active_networks.py

#!/usr/local/bin/python3
from scapy.all import IP, ICMP, TCP, UDP, ARP, sr1, srp, Ether
import target_network_input
import logging 

logging.basicConfig(level = logging.DEBUG) 

net_list = target_network_input.process_network()

#Main function to find active hosts
def active_hosts(net_list):
    live_hosts = []
    for ip in net_list:
        if icmp_ping(ip):
            live_hosts.append(ip)
        elif tcp_ping(ip):
            live_hosts.append(ip)
        elif udp_ping(ip):
            live_hosts.append(ip)
        elif arp_ping(ip):
            live_hosts.append(ip)
        else:
            continue
    print(live_hosts)
    return live_hosts
    
#Identify networks through ICMP requests 
def icmp_ping(ip):
    try:
        packet = IP(dst = ip) / ICMP()
        response = sr1(packet, timeout = 1, verbose = 0)
        return response is not None
    except Exception as e:
        return False 
    
#Identify networks through TCP requests 
def tcp_ping(ip, port = 80):
    try:
        packet = IP(dst = ip) / TCP(dport = port, flags = 'S')
        response = sr1(packet, timeout = 1, verbose = 0)
        return response and response.haslayer(TCP) and response[TCP].flags == 'SA'
    except Exception as e:
        return False
    
#Identify networks through UDP requests 
def udp_ping(ip, port = 53):
    try:
        packet = IP(dst = ip) / UDP(dport = port)
        response = sr1(packet, timeout = 1, verbose = 0)
        return response is not None
    except Exception as e:
        return False
    
#Identify networks through ARP requests
def arp_ping(ip):
    try: 
        arp_request = ARP(pdst = ip)
        broadcast = Ether(dst = 'ff:ff:ff:ff:ff:ff')
        packet = broadcast / arp_request
        response = srp(packet, timeout = 1, verbose = 0)[0]
        return len(response) > 0
    except Exception as e:
        return False 

active_hosts(net_list)

我本来的预期是:程序接收用户输入的网段,显示范围内的所有可用主机,然后逐个探测每个主机是否活跃,把活跃的主机添加到列表里最后输出,但现在每次运行都只返回[],完全找不到活跃主机。


可能的问题排查与解决建议

结合开发经验,给你列几个最可能的原因和对应的解决方法:

  • 权限不足:Scapy发送ICMP、ARP这类数据包通常需要管理员/root权限,如果用普通用户运行脚本,很多探测会直接失败返回False。解决方法:Linux/macOS下用sudo python3 active_networks.py运行,Windows右键以管理员身份打开命令提示符再执行脚本。

  • IP对象格式不兼容:ipaddress.IPv4Network.hosts()返回的是IPv4Address对象,而Scapy的IP(dst=ip)需要字符串格式的IP地址,直接传对象可能导致数据包发送失败。解决方法:在每个探测函数里把IP转成字符串,比如把ICMP ping里的packet = IP(dst = ip) / ICMP()改成packet = IP(dst = str(ip)) / ICMP(),其他三个探测函数同理修改。

  • 端口选择太局限:默认用TCP 80端口和UDP 53端口,但目标主机可能这些端口没开放,导致TCP/UDP探测失败。解决方法:要么换常用开放端口(比如TCP 22、443),要么改成多端口尝试,比如修改tcp_ping函数:

    def tcp_ping(ip, ports=[22, 80, 443]):
        for port in ports:
            try:
                packet = IP(dst=str(ip)) / TCP(dport=port, flags='S')
                response = sr1(packet, timeout=2, verbose=0)
                if response and response.haslayer(TCP) and response[TCP].flags == 'SA':
                    return True
            except Exception as e:
                print(f"TCP探测端口{port}时出错: {e}")
        return False
    
  • ARP探测的局限性:ARP协议只能在同一局域网内生效,如果目标网段不在本地局域网,ARP探测肯定会失败。解决方法:给arp_ping函数加个判断,只有当目标IP在本地网段时才用ARP探测,否则直接跳过:

    def arp_ping(ip):
        # 先获取本地IP和网段
        import socket
        def get_local_ip():
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            try:
                s.connect(('10.255.255.255', 1))
                local_ip = s.getsockname()[0]
            except Exception:
                local_ip = '127.0.0.1'
            finally:
                s.close()
            return local_ip
        local_net = ipaddress.IPv4Network(f"{get_local_ip()}/24", strict=False)
        target_ip_obj = ipaddress.IPv4Address(str(ip))
        if target_ip_obj not in local_net:
            return False  # 非本地网段,ARP无效
        try: 
            arp_request = ARP(pdst=str(ip))
            broadcast = Ether(dst='ff:ff:ff:ff:ff:ff')
            packet = broadcast / arp_request
            response = srp(packet, timeout=2, verbose=0)[0]
            return len(response) > 0
        except Exception as e:
            print(f"ARP探测出错: {e}")
            return False 
    
  • 超时时间太短:1秒的超时在网络延迟高的环境下可能不够,导致数据包还没收到响应就超时了。解决方法:把各个探测函数的timeout改成2或3秒。

  • 异常捕获太隐蔽:每个探测函数都用except Exception as e:捕获所有异常且直接返回False,看不到具体错误信息很难排查。解决方法:暂时去掉异常捕获,或者在异常里打印错误信息,比如:

    except Exception as e:
        print(f"ICMP探测{ip}时出错: {e}")
        return False
    

另外,可以在active_hosts函数里加一些打印日志,看看每个IP的探测情况,方便定位问题:

def active_hosts(net_list):
    live_hosts = []
    for ip in net_list:
        print(f"正在探测主机: {ip}")
        if icmp_ping(ip):
            print(f"✅ {ip} 通过ICMP探测确认活跃")
            live_hosts.append(ip)
        elif tcp_ping(ip):
            print(f"✅ {ip} 通过TCP探测确认活跃")
            live_hosts.append(ip)
        elif udp_ping(ip):
            print(f"✅ {ip} 通过UDP探测确认活跃")
            live_hosts.append(ip)
        elif arp_ping(ip):
            print(f"✅ {ip} 通过ARP探测确认活跃")
            live_hosts.append(ip)
        else:
            print(f"❌ {ip} 未探测到活跃")
            continue
    print(f"\n最终活跃主机列表: {live_hosts}")
    return live_hosts

建议先从权限问题和IP格式转换这两个最基础的点入手排查,这两个是导致空列表最常见的原因,应该能解决大部分问题。


备注:内容来源于stack exchange,提问作者prince singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:13:01