如何编写端口扫描脚本

wen 实用脚本 2

从零到精通的实战指南(含Python与Bash双实现)

目录导读

  1. 端口扫描原理与基础概念 - 理解TCP/UDP协议、三次握手与端口状态
  2. 脚本语言选型与工具对比 - Python vs Bash vs Nmap,如何选择最优方案
  3. Python端口扫描脚本实战 - 完整代码解析(多线程+超时控制+错误处理)
  4. Bash脚本极简实现 - 用/dev/tcp与nc命令编写轻量级扫描器
  5. 进阶优化:并发控制与隐蔽性 - 避免被IDS检测的实用技巧
  6. 常见问题FAQ - 5个高频问答解决你的开发困惑
  7. 安全合规与伦理提示 - 合法使用边界与法律责任

端口扫描原理与基础概念

端口扫描的本质是探测目标主机特定端口的状态,在TCP/IP协议栈中,端口范围0-65535,其中0-1023为知名端口(如HTTP=80,HTTPS=443),扫描器通过发送精心构造的数据包,根据响应特征判断端口处于以下三种状态:

如何编写端口扫描脚本

  • Open(开放):目标返回SYN+ACK,表示服务在监听
  • Closed(关闭):目标返回RST,表示无服务
  • Filtered(被过滤):无响应或返回ICMP不可达,通常有防火墙拦截

核心原理:TCP三次握手的“半开扫描”(SYN扫描)是最经典的隐蔽技术——只发送SYN包,收到SYN+ACK后立即发送RST断开,不建立完整连接,从而避免留下系统日志。


脚本语言选型与工具对比

方案 复杂度 速度 隐蔽性 适用场景
Python + socket 中(可多线程) 高(自定义包) 学习、定制化需求
Bash + /dev/tcp 快速临检
Nmap 高(功能丰富) 极快 极高 专业渗透测试

选型建议:若追求代码可读性和跨平台性,Python 是首选;若在Linux环境只需快速检测,Bash 足够;若需要指纹识别、漏洞探测,直接调用Nmap的python-nmap库更高效。


Python端口扫描脚本实战(完整代码)

以下是一个支持多线程、超时控制、彩色输出的高级脚本:

#!/usr/bin/env python3
import socket
import threading
from queue import Queue
class PortScanner:
    def __init__(self, target, start_port, end_port, timeout=0.5, threads=100):
        self.target = target
        self.start = start_port
        self.end = end_port
        self.timeout = timeout
        self.threads = threads
        self.queue = Queue()
        self.open_ports = []
        self.lock = threading.Lock()
    def scan_port(self, port):
        """扫描单个端口"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(self.timeout)
            result = sock.connect_ex((self.target, port))
            if result == 0:
                with self.lock:
                    self.open_ports.append(port)
                    print(f"[+] 端口 {port} 开放")
            sock.close()
        except socket.timeout:
            pass  # 超时视为过滤状态
        except Exception as e:
            print(f"[-] 扫描端口 {port} 异常: {e}")
    def worker(self):
        """线程工作函数"""
        while not self.queue.empty():
            port = self.queue.get()
            self.scan_port(port)
            self.queue.task_done()
    def run(self):
        """主控制逻辑"""
        print(f"开始扫描 {self.target} (端口 {self.start}-{self.end})...")
        # 填充队列
        for port in range(self.start, self.end + 1):
            self.queue.put(port)
        # 启动线程
        thread_pool = []
        for _ in range(self.threads):
            t = threading.Thread(target=self.worker)
            t.start()
            thread_pool.append(t)
        # 等待完成
        self.queue.join()
        for t in thread_pool:
            t.join()
        # 汇总输出
        print(f"\n扫描完成!共发现 {len(self.open_ports)} 个开放端口:")
        print(sorted(self.open_ports))
if __name__ == "__main__":
    # 使用示例:python scanner.py 192.168.1.1 1 1000
    import sys
    if len(sys.argv) != 4:
        print("用法: python scanner.py <目标IP> <起始端口> <结束端口>")
        sys.exit(1)
    target_ip = sys.argv[1]
    start = int(sys.argv[2])
    end = int(sys.argv[3])
    scanner = PortScanner(target_ip, start, end)
    scanner.run()

关键优化点说明

  • 多线程:通过threadingQueue实现并发,100线程可将1-1000端口扫描时间压缩到10秒内
  • 超时控制settimeout(0.5)避免卡死在无响应的端口
  • 线程锁lock保证open_ports列表的写入安全
  • 错误处理:捕获超时、连接拒绝、DNS解析失败等异常

Bash脚本极简实现(适合应急)

Linux环境下无需安装任何依赖,利用/dev/tcp伪设备即可:

#!/bin/bash
# usage: ./scan.sh <target> <start> <end>
TARGET=$1
START=$2
END=$3
for ((port=$START; port<=$END; port++)); do
    (echo >/dev/tcp/$TARGET/$port) 2>/dev/null && echo "端口 $port 开放"
done
echo "扫描完成"

性能提升:使用nc -z -w 1 + xargs -P并行化:

seq $START $END | xargs -P 50 -I {} sh -c 'nc -z -w 1 '$TARGET' {} 2>/dev/null && echo "{} open"'

缺点提醒:Bash方案无法识别“过滤”状态,且速度较慢(约每端口0.5秒),仅适合小范围探测。


进阶优化:并发控制与隐蔽性

1 隐蔽性技术

  • 延迟扫描:每端口增加随机0.1-1秒延迟,避免突发流量
  • 随机化端口顺序:不按顺序扫描,打乱探测模式
  • 源地址伪造(高级):使用Scapy库伪造IP头(需root权限)

2 Python并发升级

改用asyncio协程比多线程更轻量:

import asyncio
async def check_port(target, port):
    try:
        reader, writer = await asyncio.wait_for(
            asyncio.open_connection(target, port), timeout=0.5)
        writer.close()
        return port
    except:
        return None
async def main():
    tasks = [check_port("example.com", p) for p in range(1, 1000)]
    results = await asyncio.gather(*tasks)
    open_ports = [r for r in results if r]
    print("开放端口:", open_ports)
asyncio.run(main())

常见问题FAQ(5个高频问答)

Q1:为什么我的脚本扫描速度极慢? A:通常是未启用并发,Python中务必使用线程池(ThreadPoolExecutor)或asyncio,Bash脚本推荐xargs -P,过大的超时时间(如>3秒)累计会成倍增加耗时。

Q2:扫描结果出现大量假阳性/漏报? A:防火墙可能丢弃RST包导致“超时误报为关闭”,建议增加重试机制(最多2次),并对比nmap -sS结果校验,若目标有负载均衡(如云服务),需多IP段对比。

Q3:如何识别端口对应的服务版本? A:在探测到开放端口后,发送特定的应用层探测字符串(如发送HEAD / HTTP/1.0\r\n\r\n到80端口),解析返回的Banner信息,更简单的方法是调用nmap -sV,或用Python的socket.recv(1024)接收banner。

Q4:脚本遇到大规模网段扫描(如/24子网)内存崩溃? A:不要一次性将所有IP放入队列,采用分段扫描:每处理完一个IP即释放内存,推荐使用生成器(Python的yield)逐个产生IP。

Q5:扫描时被目标封禁IP怎么办? A:配置代理或VPN轮换IP;降低扫描速率(增加延迟);使用分布式扫描架构(如分片扫描),注意:主动规避封禁可能违反目标使用条款,需谨慎!


安全合规与伦理提示

⚠️ 法律红线:未经授权扫描网络可能导致《网络安全法》《刑法》第285条“非法侵入计算机信息系统罪”追责,合法场景仅为:1) 自身资产安全评估;2) 获得书面授权的渗透测试;3) CTF比赛或实验室环境。

合规操作建议

  • 扫描前从目标管理员处获取书面授权书
  • 控制扫描强度,避免影响业务可用性(建议每秒<50个包)
  • 扫描结果仅用于防护加固,禁止泄露他人隐私

总结与延伸阅读

本文从TCP协议原理入手,提供了Python多线程实现(灵活定制)和Bash快速方案(轻量应急),并深入探讨了并发优化、隐蔽性技巧及法律风险,如需工业级扫描能力,建议直接学习Nmap Scripting Engine (NSE)Masscan源码。

本篇文章的核心方法论先懂协议(原理),再选工具(语言),继而优化性能(并发),最终敬畏规则(合规),掌握这四步,你编写的端口扫描器将不仅高效可靠,更安全合法。

抱歉,评论功能暂时关闭!