基于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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、