satyamsingh12345/port-scanner

GitHub: satyamsingh12345/port-scanner

一个基于 Python 标准库构建的轻量级多线程 TCP 端口扫描器,通过并发连接探测目标主机端口状态并自动记录日志。

Stars: 0 | Forks: 0

# port-scanner 一个使用 Python 构建的多线程 TCP 端口扫描器 —— 可以扫描单个主机或端口范围,将结果分类为 open/closed/timeout,并将所有内容记录到控制台和文件中。旨在学习 socket 编程和并发。 # TCP 端口扫描器 一个使用 Python 编写的轻量级、多线程 **TCP 端口扫描器**。作为一个实践项目构建,用于学习 **socket 编程** 和 **并发** (线程)基础知识 —— 这些是网络安全和 SOC 分析师工作的核心技能。 ## 目录 - [功能](#features) - [工作原理](#how-it-works) - [项目结构](#project-structure) - [环境要求](#requirements) - [安装说明](#installation) - [使用说明](#usage) - [示例](#examples) - [输出示例](#sample-output) - [日志记录](#logging) - [错误处理](#error-handling) - [法律 / 道德声明](#legal--ethical-notice) - [我的学习心得](#what-i-learned) - [可能的改进](#possible-improvements) - [许可证](#license) ## 功能 - 扫描**单个主机**的某个端口、端口列表或整个端口范围。 - 使用 **多线程** (`ThreadPoolExecutor`) 扫描,可快速获得数百个端口的扫描结果。 - 将每个端口分类为 **open**、**closed** 或 **timeout/error**。 - 尝试识别 open 端口的常见服务名称(例如 `80 → http`)。 - 将结果记录到 **控制台和带有时间戳的日志文件中**。 - 支持自定义超时时间和线程数。 - 能够优雅地处理不可达主机、DNS 解析失败和 `Ctrl+C` 中断。 ## 工作原理 扫描器使用 Python 内置的 `socket` 模块尝试与每个目标端口建立 TCP 连接: 1. 为目标 IP 和端口创建一个 TCP socket。 2. `connect_ex()` 尝试进行 TCP 三次握手,但不会在失败时引发异常(这与 `connect()` 不同),这使得它非常适合用于扫描大量端口。 3. 返回值为 `0` 表示端口 **open**(连接成功)。任何其他值都表示端口 **closed** 或主动拒绝连接。 4. 每个端口都在各自的线程中进行扫描,并提交给 `concurrent.futures.ThreadPoolExecutor`,因此可以并行检查数百个端口,而不是逐个检查。 5. `threading.Lock` 可防止多个线程同时写入控制台/日志而导致输出混乱。 ## 项目结构 ``` port-scanner/ ├── port_scanner.py # Main script — all scanning logic and CLI ├── requirements.txt # Dependencies (none beyond the standard library) ├── logs/ # Auto-created; timestamped scan logs land here │ └── .gitkeep ├── LICENSE ├── .gitignore └── README.md ``` ## 环境要求 - Python **3.8+** - 无需第三方包 —— 使用的所有模块(`socket`、`threading`、`argparse`、`logging`、`concurrent.futures`)都是 Python 标准库的一部分。 ## 安装说明 ``` git clone https://github.com//port-scanner.git cd port-scanner ``` 不需要执行 `pip install` 步骤,但为了完整性及满足未来的依赖需求,项目中仍包含了 `requirements.txt` 文件。 ## 使用说明 ``` python port_scanner.py -H [-p ] [-t ] [-T ] ``` ### 参数 | 标志 | 完整形式 | 描述 | 默认值 | |------|--------------|-------------------------------------------------------------------|------------| | `-H` | `--host` | 目标主机名或 IP 地址(**必填**) | — | | `-p` | `--ports` | 要扫描的端口 —— 单个、逗号分隔列表、范围或混合形式 | `1-1024` | | `-t` | `--timeout` | 每个连接的超时时间(秒) | `1.0` | | `-T` | `--threads` | 最大并发线程数 | `100` | ### `--ports` 接受的端口格式 | 格式 | 示例 | 含义 | |-----------------|-------------------|------------------------------------| | 单个端口 | `80` | 仅扫描端口 80 | | 逗号分隔列表 | `22,80,443` | 仅扫描这些指定端口 | | 范围 | `1-1024` | 扫描从 1 到 1024 的每一个端口 | | 混合 | `22,80,1000-1010` | 组合使用列表和范围 | ## 示例 使用默认参数扫描主机的前 1024 个端口: ``` python port_scanner.py -H scanme.nmap.org ``` 使用较短的超时时间和更多线程扫描特定范围: ``` python port_scanner.py -H 192.168.1.1 -p 1-65535 -t 0.5 -T 200 ``` 仅扫描少数知名端口: ``` python port_scanner.py -H example.com -p 22,80,443,3306 ``` ## 输出示例 ``` Log file: logs/scan_20260727_094200.log ============================================================ Target : scanme.nmap.org (45.33.32.156) Ports : 1024 total Timeout : 1.0s Threads: 100 Started : 2026-07-27 09:42:00 ============================================================ [OPEN] Port 22 (ssh) [OPEN] Port 80 (http) ============================================================ SCAN SUMMARY Open : [22, 80] Closed : 1020 ports Timeouts: 2 ports Errors : 0 ports Duration: 4.87s ============================================================ ``` ## 日志记录 每次运行都会在 `logs/` 目录中生成一个带有时间戳的新文件,例如 `logs/scan_20260727_094200.log`。日志文件包含与打印到控制台完全相同的信息:扫描配置、发现的每个 open 端口、任何超时/错误以及最终摘要。这方便您保留过去扫描的记录,或将其附加到报告中。 ## 错误处理 扫描器被设计为优雅地失败,而不是直接崩溃: - **无法解析的主机名** (`socket.gaierror`) → 打印明确的致命错误并退出,而不是抛出 traceback。 - **连接超时** → 该端口将被记录为 `timeout`,扫描继续进行。 - **其他 socket 错误**(例如网络不可达) → 该端口会被记录为 `error`;其余的扫描不受影响。 - **扫描期间按下 Ctrl+C** → 会被捕获并报告为扫描被中断,而不是显示原始的堆栈跟踪。 - **无效的 `--ports` 输入**(例如 `abc`、反向的范围) → 在任何扫描开始之前都会被捕获并报告。 ## 法律 / 道德声明 仅扫描您 **拥有** 或已获得 **明确书面许可** 进行测试的主机和网络。未经授权的端口扫描可能会违反法律(如美国《计算机欺诈和滥用法》或其他地区的类似立法),并且也可能违反 ISP 或云服务提供商的可接受使用政策。`scanme.nmap.org` 由 Nmap 项目提供,专门用于安全、合法的扫描练习。 ## 我的学习心得 - 从客户端 socket 的角度来看,TCP 三次握手是如何进行的,以及在扫描用例中 `connect_ex()` 与 `connect()` 有何不同。 - 如何使用 `ThreadPoolExecutor` 对 I/O 密集型工作进行并行化,而不是手动管理线程。 - 当许多线程并发写入时,为什么共享输出(控制台/日志)需要加锁。 - 使用 `argparse` 构建 CLI 工具,包括为灵活的 `--ports` 格式添加自定义验证。 - 设计日志记录机制,使相同的输出在实时(控制台)和事后(日志文件)都能发挥作用。 ## 可能的改进 - 添加 UDP 扫描支持。 - 为 open 端口添加 banner grabbing 功能(读取服务的欢迎消息)。 - 将结果导出为 JSON/CSV 格式,以便更容易地与其他工具集成。 - 使用精选的最常见 open 端口列表,添加 `--top-ports` 模式,而不是使用完整范围。 - 使用 `asyncio` 实现异步版本,以便与多线程方法进行对比。 ## 许可证 该项目基于 [MIT 许可证](LICENSE) 授权。
标签:Python, TCP/IP, 后端开发, 插件系统, 数据统计, 无后门, 端口扫描, 网络工具, 逆向工具