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

Python网络扫描脚本无有效输出问题排查及修正需求

问题分析

你的脚本执行后无有效端口结果,核心原因是ARP扫描仅适用于局域网环境,而你扫描的是公网IP段(18.177.16.0/24属于AWS公网地址),ARP无法跨路由获取响应,导致没有发现存活主机,后续端口扫描自然无法执行。此外,原端口扫描的判断逻辑也未考虑防火墙过滤SYN包的情况。

修正后的代码
import scapy.all as scapy
import argparse
import json

def get_arguments():
    parser = argparse.ArgumentParser(description="Network Scanner")
    parser.add_argument("target", help="Target IP address or range (CIDR notation)")
    parser.add_argument("-p", "--ports", default="1-1024", help="Ports to scan (default: 1-1024)")
    parser.add_argument("-o", "--output", choices=["json", "csv"], help="Output format (json/csv)")
    return parser.parse_args()

def scan_port(ip, port):
    src_port = 12345
    try:
        # 发送SYN包
        response = scapy.sr1(scapy.IP(dst=ip)/scapy.TCP(sport=src_port, dport=port, flags="S"), 
                             timeout=1, verbose=False)
        if not response:
            # 无响应,可能被防火墙过滤
            return port, "filtered"
        elif response.haslayer(scapy.TCP):
            if response.getlayer(scapy.TCP).flags == 0x12:
                # 收到SYN-ACK,端口开放,发送RST关闭连接
                scapy.send(scapy.IP(dst=ip)/scapy.TCP(sport=src_port, dport=port, flags="R"), 
                           verbose=False)
                return port, "open"
            elif response.getlayer(scapy.TCP).flags == 0x14:
                # 收到RST,端口关闭
                return port, "closed"
        return port, "unknown"
    except Exception as e:
        return port, f"error: {str(e)}"

def scan_host(ip, ports):
    open_ports = []
    for port in range(ports[0], ports[1] + 1):
        port_num, status = scan_port(ip, port)
        if status == "open":
            open_ports.append(port_num)
    return {ip: open_ports}

def scan_network(target, ports_range):
    print("Scanning network for live hosts...")
    # 用ICMP ping探测存活主机(适用于公网/局域网)
    ping_packet = scapy.IP(dst=target)/scapy.ICMP()
    answered_list = scapy.sr(ping_packet, timeout=2, verbose=False)[0]
    
    scan_results = {}
    for element in answered_list:
        ip = element[1].src
        print(f"Found live host: {ip}, starting port scan...")
        scan_results.update(scan_host(ip, ports_range))

    print("Scan completed.")
    return scan_results

def main():
    args = get_arguments()
    target = args.target
    ports_range = list(map(int, args.ports.split("-")))

    print(f"Scanning target: {target}")
    print(f"Scanning ports: {ports_range[0]}-{ports_range[1]}")
    print(f"Output format: {args.output}")

    scan_results = scan_network(target, ports_range)
    print("Scan results:", scan_results)

    if args.output == "json":
        with open("scan_results.json", "w") as file:
            json.dump(scan_results, file, indent=4)
        print("Results saved to 'scan_results.json'")
    elif args.output == "csv":
        with open("scan_results.csv", "w") as file:
            file.write("IP Address,Open Ports\n")
            for ip, ports in scan_results.items():
                file.write(f"{ip},{','.join(map(str, ports))}\n")
        print("Results saved to 'scan_results.csv'")
    else:
        for ip, ports in scan_results.items():
            print(f"IP: {ip}\tOpen Ports: {', '.join(map(str, ports)) if ports else 'None'}")

if __name__ == "__main__":
    main()
关键修改说明
  • 替换网络探测方式:将ARP扫描改为ICMP ping,适配公网和局域网环境,能正确发现存活主机
  • 优化端口扫描逻辑:
    • 区分开放(SYN-ACK响应)、关闭(RST响应)、过滤(无响应)三种状态
    • 发现开放端口后主动发送RST包关闭半连接,避免资源占用
  • 输出格式优化:CSV文件增加表头,无开放端口时显示None,提升可读性
  • 超时调整:延长ping超时到2秒,提升公网主机探测成功率

内容的提问来源于stack exchange,提问作者Gabriel D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:35:57