基于Scapy库与线程池技术的并发TCP SYN半开扫描算法研究及实现

2024-03-13 09:36

本文主要是介绍基于Scapy库与线程池技术的并发TCP SYN半开扫描算法研究及实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

现了一个基于Python的TCP SYN扫描工具,采用Scapy库构造和解析网络报文,并采用线程池技术提高扫描效率。

实现原理

TCP SYN扫描的原理是利用了TCP连接建立过程中的三次握手特性,以半开连接(Half-open scanning)的方式探测目标主机的服务端口是否开放。具体步骤如下:

  1. 三次握手过程:
  • 在正常情况下,客户端(即扫描器)发起一个TCP连接时,会发送一个SYN(同步序列编号)报文到服务器。
  • 服务器接收到SYN报文后,如果该端口处于监听状态,则会回复一个SYN+ACK(同步并确认)报文作为回应。
  • 客户端在接收到SYN+ACK之后,通常会回复一个ACK(确认)报文完成三次握手,然后双方就可以开始传输数据。
  1. SYN扫描技术:
  • 在TCP SYN扫描中,扫描器模拟正常的连接请求,向目标主机和指定端口发送一个SYN报文。
  • 如果目标端口是开放的,它会返回一个SYN+ACK报文;若端口未打开或被防火墙阻止,则会返回一个RST(复位)报文。
  • 但是,不同于正常的连接建立过程,扫描器在接收到SYN+ACK报文后,并不会继续完成第三次握手(即不发送ACK),而是直接丢弃这个连接尝试,因此不会建立起完整的连接。
  • 根据收到的响应类型,扫描器就能判断端口的状态:收到SYN+ACK则认为端口开放,收到RST则认为端口关闭或不可达。

运行流程

本TCP SYN扫描工具的执行过程如下:

  1. 初始化阶段:
  • 引入必要的Python库,包括scapy.all、argparse、logging以及concurrent.futures.ThreadPoolExecutor。
  • 设置Scapy运行时日志级别为ERROR,以减少无关输出。
  • 定义命令行参数解析器argparse.ArgumentParser,用于接收用户输入的被扫描主机IP地址(通过"-H"或"–host"指定)和端口范围(通过"-p"或"–ports"指定,默认值为"1-1024")。
  1. 参数处理阶段:
  • 解析用户输入的参数,若同时提供了主机IP地址和端口范围,则将端口范围字符串按’-'分割后转化为整数列表,并生成相应的端口号序列。
  1. 扫描准备阶段:
  • 函数tcpSynScan_single(target, port)针对单个目标端口进行TCP SYN半打开扫描。该函数构造一个SYN标志设置为“S”的TCP数据包并发送至指定主机和端口,根据返回的数据包判断端口状态。
  1. 并发扫描阶段:
  • 函数tcpSynScan_parallel(target, ports)利用线程池ThreadPoolExecutor实现对目标主机多个端口的同时扫描。
  • 将目标主机IP地址与待扫描的端口列表作为参数传递给executor.map()函数,它会并发地调用tcpSynScan_single对每个端口执行扫描操作。
  • 扫描结果以布尔值形式存储在results变量中,对应表示各个端口是否开放。
  1. 结果展示阶段:
  • 使用zip(ports, results)将扫描结果与原始端口号配对,然后循环遍历这些配对信息。
  • 对于检测到开放的端口,在控制台输出格式化的信息,内容包括:扫描主机IP地址、端口号以及其状态(开放或关闭)。

综上所述,整个项目实现了从参数接收、并发扫描到结果显示的完整TCP SYN扫描流程,有效地提升了扫描效率且保持了对目标主机端口状态准确判断的能力。

代码实现

执行单个端口的TCP SYN扫描。
tcpSynScan_single(target, port):针对单个目标端口执行TCP SYN半打开扫描技术。通过发送一个SYN标志设置为“S”的TCP报文至指定IP地址的目标主机和端口,并监测其响应。若目标端口对SYN报文返回SYN+ACK(表示端口开放),则函数返回True;否则,若收到RST(复位)标志或无响应,则认为端口关闭,函数返回False。

def tcpSynScan_single(target, port):"""执行单个端口的TCP SYN扫描。参数:- target: 目标主机的IP地址。- port: 要扫描的端口号。返回值:- 如果端口对SYN报文响应为开放(SA),则返回True;- 如果端口响应为关闭(RST),或无响应,则返回False。"""send = sr1(IP(dst=target) / TCP(dport=port, flags="S"), timeout=2, verbose=0)if (send is None):return Falseelif send.haslayer("TCP"):if send["TCP"].flags == "SA":return Trueelif send["TCP"].flags in ["RA", "R"]:  # RST响应return Falseelse:return False

并行执行TCP SYN扫描。
tcpSynScan_parallel(target, ports):在给定的目标主机上并发地对多个端口执行tcpSynScan_single函数,利用线程池ThreadPoolExecutor以优化资源分配与提高扫描速度。该函数接收一个IP地址和端口列表作为输入参数,扫描完成后将打印出所有开放端口的相关信息。


def tcpSynScan_parallel(target, ports):"""并行执行TCP SYN扫描。参数:- target: 目标主机的IP地址。- ports: 要扫描的端口列表。说明:使用线程池并发地对多个端口执行tcpSynScan_single函数。"""with ThreadPoolExecutor(max_workers=50) as executor:  results = executor.map(tcpSynScan_single, [target] * len(ports), ports)for port, is_open in zip(ports, results):status = "开放" if is_open else "关闭"if status == "开放":print("[+] 扫描主机: %-13s 端口: %-5s %s" % (target, port, status))

参数设置

if __name__ == "__main__":logging.getLogger("scapy.runtime").setLevel(logging.ERROR)parser = argparse.ArgumentParser(description='TCP SYN扫描工具')parser.add_argument("-H", "--host", dest="host", help="输入一个被扫描主机IP地址")parser.add_argument("-p", "--ports", dest="ports", default="1-1024", help="输入端口范围,默认为1-1024")args = parser.parse_args()if args.host and args.ports:start, end = map(int, args.ports.split('-'))ports = list(range(start, end + 1))tcpSynScan_parallel(args.host, ports)else:parser.print_help()

优化建议

  1. 线程池参数调整: 目前程序设置的线程池最大工作线程数为50,这一数值可以根据目标主机的网络状况、系统资源和实际需求进行动态调整。可以通过实验评估不同数量的工作线程对扫描效率和系统负载的影响,选择最佳线程数。

  2. 超时时间优化: 代码中sr1()函数的超时时间为2秒,这个值可能不足以应对所有网络环境下的响应情况,可以考虑增加一个配置选项允许用户自定义超时时间,以适应不同的网络延迟。

  3. 错误处理与重试机制: 在网络不稳定或目标主机有防护措施的情况下,单次SYN请求可能会失败。为了提高扫描稳定性,可以添加重试机制,当某端口在首次扫描无响应或者收到非预期响应时,在设定次数内重新尝试发送SYN报文。

  4. 结果存储与展示: 当扫描大量端口时,仅打印出开放端口的信息可能不够全面。可将扫描结果保存至文件,便于后续分析。同时,可考虑提供更详细的结果输出选项,如显示扫描进度、总扫描耗时等信息。

  5. 资源消耗控制: 考虑到大规模扫描可能会导致系统资源(CPU、内存、网络带宽)过度消耗,应引入资源限制策略,例如,根据系统的可用资源动态调节线程池大小,或在检测到系统资源紧张时暂停部分扫描任务。

  6. 合法性检查与合规性: 实施网络扫描前,确保符合当地法律法规和网络使用政策,并对目标IP地址进行合法性验证,防止误操作或其他法律风险。

  7. 性能监控与调优: 可以添加性能监控模块,实时记录并分析扫描过程中的各项指标,包括线程执行情况、CPU和内存占用、网络流量等,为进一步优化提供数据支持。

这篇关于基于Scapy库与线程池技术的并发TCP SYN半开扫描算法研究及实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/804410

相关文章

Redis实现分布式锁全过程

《Redis实现分布式锁全过程》文章介绍Redis实现分布式锁的方法,包括使用SETNX和EXPIRE命令确保互斥性与防死锁,Redisson客户端提供的便捷接口,以及Redlock算法通过多节点共识... 目录Redis实现分布式锁1. 分布式锁的基本原理2. 使用 Redis 实现分布式锁2.1 获取锁

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

使用SpringBoot+InfluxDB实现高效数据存储与查询

《使用SpringBoot+InfluxDB实现高效数据存储与查询》InfluxDB是一个开源的时间序列数据库,特别适合处理带有时间戳的监控数据、指标数据等,下面详细介绍如何在SpringBoot项目... 目录1、项目介绍2、 InfluxDB 介绍3、Spring Boot 配置 InfluxDB4、I

基于Java和FFmpeg实现视频压缩和剪辑功能

《基于Java和FFmpeg实现视频压缩和剪辑功能》在视频处理开发中,压缩和剪辑是常见的需求,本文将介绍如何使用Java结合FFmpeg实现视频压缩和剪辑功能,同时去除数据库操作,仅专注于视频处理,需... 目录引言1. 环境准备1.1 项目依赖1.2 安装 FFmpeg2. 视频压缩功能实现2.1 主要功

使用Python实现无损放大图片功能

《使用Python实现无损放大图片功能》本文介绍了如何使用Python的Pillow库进行无损图片放大,区分了JPEG和PNG格式在放大过程中的特点,并给出了示例代码,JPEG格式可能受压缩影响,需先... 目录一、什么是无损放大?二、实现方法步骤1:读取图片步骤2:无损放大图片步骤3:保存图片三、示php

使用Python实现一个简易计算器的新手指南

《使用Python实现一个简易计算器的新手指南》计算器是编程入门的经典项目,它涵盖了变量、输入输出、条件判断等核心编程概念,通过这个小项目,可以快速掌握Python的基础语法,并为后续更复杂的项目打下... 目录准备工作基础概念解析分步实现计算器第一步:获取用户输入第二步:实现基本运算第三步:显示计算结果进

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

Python利用PySpark和Kafka实现流处理引擎构建指南

《Python利用PySpark和Kafka实现流处理引擎构建指南》本文将深入解剖基于Python的实时处理黄金组合:Kafka(分布式消息队列)与PySpark(分布式计算引擎)的化学反应,并构建一... 目录引言:数据洪流时代的生存法则第一章 Kafka:数据世界的中央神经系统消息引擎核心设计哲学高吞吐

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、