Narandan/network-security-scanner
GitHub: Narandan/network-security-scanner
一个基于 Python 原生 socket 和多线程从零构建的轻量级 TCP 端口扫描器,用于识别开放端口、常见服务并抓取 Banner,适合网络安全学习与基础评估。
Stars: 0 | Forks: 0
# 网络安全扫描器
一个轻量级、多线程的 TCP 端口扫描器,使用 Python 从零开始通过原始 socket 编程构建。它能扫描目标主机,识别开放端口,将其映射到常见服务,并可选择抓取服务 Banner——这与真实网络安全评估中使用的(在生产环境中使用 Nmap 之前)基础技术相同。
作为一个学习/作品集项目构建,旨在通过原始代码而非封装现有工具来展示核心网络、并发和安全评估概念。
## 实际功能
- 将主机名解析为 IP 地址
- 尝试对一组目标端口执行 **TCP connect 扫描**(完整的三次握手)
- 使用线程池**并发**运行这些连接尝试,因为扫描是 I/O 密集型的(等待的是网络,而不是 CPU)
- 使用精选的查找表将开放端口映射到其传统服务名称(SSH、HTTP、MySQL 等)
- 可选地抓取服务在连接时发送的原始 Banner,以确认实际运行的内容,而不是仅凭端口号进行猜测
- 打印简洁的终端报告,并可将结果导出为 JSON
## 刻意*不*做的事
这是一个侦察/评估工具,而不是攻击工具:
- 不使用原始 socket SYN(“半开”)扫描——这需要提升的权限和超出本项目范围的数据包伪造。这里使用标准的操作系统 socket API (`connect()`),与任何客户端应用程序使用的基础方法相同。
- 不进行漏洞利用、暴力破解或漏洞扫描
- 不试图绕过防火墙、IDS 或日志记录
- 不声称能替代 Nmap——本项目端到端涵盖了一个狭窄且易于理解的领域(TCP connect 扫描 + 服务识别 + Banner 抓取),这些代码我可以完全解释,而不是一个我无法解释的宽泛功能集。
## 设计初衷
| 决策 | 原因 |
|---|---|
| TCP **connect** 扫描,而非 SYN 扫描 | 适用于非特权 socket,跨平台可移植,且其行为完全可解释——无需进行原始数据包伪造。 |
| 使用 `ThreadPoolExecutor`,而非 `asyncio` | 工作负载是大量简短、独立且受 I/O 限制的 socket 调用。线程能清晰地映射到这些调用上,且所需的代码远少于异步重写,此外,其并发机制(在阻塞 I/O 期间释放 GIL)在面试中也很容易解释。 |
| 限制工作线程数量(`--threads`,默认 100) | 无限制的并发看起来像——或者确实会导致——对目标的拒绝服务攻击,并可能耗尽本地文件描述符。限制线程池的数量既更负责任,也更符合实际。 |
| 静态服务查找表 | 确定性强且可移植(不依赖于操作系统的 `/etc/services`),并坦诚这只是一个*提示*,而非保证——因此 Banner 抓取作为一种检验现实的方式存在。 |
| Banner 抓取是可选的(`--banner`)且是被动的 | 它仅读取服务器提供的内容(或响应诸如 HTTP `HEAD` 请求等最小、无害的探测)。不进行身份验证尝试,不进行协议漏洞利用。 |
| 按职责划分模块 | `scanner.py`(引擎)、`services.py`(数据)、`banner.py`(可选探测)、`report.py`(输出)、`cli.py`(参数解析/组装)——每个模块都可以独立阅读、测试和解释。 |
## 项目结构
```
network-security-scanner/
├── main.py # Entry point: python main.py [options]
├── network_scanner/
│ ├── __init__.py
│ ├── scanner.py # Core scan engine: sockets + concurrency
│ ├── services.py # Port -> service name lookup table
│ ├── banner.py # Optional passive banner grabbing
│ ├── report.py # Terminal + JSON output formatting
│ └── cli.py # Argument parsing and program entry point
├── tests/
│ ├── __init__.py
│ └── test_scanner.py # Unit tests, incl. a real localhost scan
├── examples/
│ └── sample_scan_output.json
├── requirements.txt
├── LICENSE
└── README.md
```
## 安装
需要 Python 3.8+。没有第三方依赖——一切都在标准库上运行。
```
git clone https://github.com/Narandan/network-security-scanner.git
cd network-security-scanner
```
就是这样——运行扫描器本身不需要 `pip install` 任何东西。
## 用法
```
# 扫描目标的常见端口(默认端口列表)
python main.py scanme.nmap.org
# 扫描特定端口范围
python main.py 192.168.1.1 -p 1-1024
# 扫描特定端口列表
python main.py 192.168.1.1 -p 22,80,443,3306
# 增加并发数(默认为 100 个 worker)
python main.py 192.168.1.1 -p 1-1024 --threads 250
# 从开放端口抓取服务 banner
python main.py 192.168.1.1 --banner
# 将结果保存为 JSON
python main.py 192.168.1.1 --banner -o results.json
# 全部选项
python main.py --help
```
## 输出示例
这是本地运行的真实输出——在 `127.0.0.1` 上启动了两个临时的 TCP 服务器(一个模拟 SSH banner,一个模拟 HTTP 响应),并在启用 `--banner` 的情况下进行了扫描:
```
Scanning 127.0.0.1 (8 ports, 50 concurrent workers)...
============================================================
Network Security Scanner - Scan Report
============================================================
Target : 127.0.0.1 (127.0.0.1)
Ports scanned : 8
Duration : 0.05s
------------------------------------------------------------
PORT STATE SERVICE BANNER
----------------------------------------------------------
2222 open Unknown SSH-2.0-OpenSSH_9.6
8080 open HTTP-Alt HTTP/1.0 200 OK
============================================================
```
请注意,端口 2222 显示服务为 `Unknown`,因为它不在端口 -> 服务查找表中(SSH 通常运行在 22 端口上,而不是 2222)——这正是 Banner 抓取旨在捕捉的端口惯例与现实之间的差异。当您自己针对真实主机运行此操作时,请使用标准端口(例如 `-p 22,80,443`)或您自己的实验室 VM,以查看它们如何被映射为名称。
本次运行的匹配 JSON 导出文件包含在 [`examples/sample_scan_output.json`](examples/sample_scan_output.json) 中。
## 运行测试
```
python -m unittest discover tests -v
```
测试套件涵盖了端口字符串解析(单个端口、范围、逗号分隔列表、无效输入),并针对 `127.0.0.1` 上的临时 TCP 服务器运行真实扫描,以端到端地测试实际的 socket 路径,而不是将其模拟掉。
## 展示的网络安全与网络概念
- **TCP 三次握手**:connect 扫描的“开放”结果*就是*一次完成的 SYN → SYN/ACK → ACK 握手——本项目是对该机制的实践演示,而不仅仅是书本上的定义。
- **作为评估阶段的侦察**:识别主机上暴露的内容是安全评估中标准的第一步,此处在不进行任何漏洞利用的情况下完成。
- **服务指纹识别与假设的对比**:该工具将“端口惯例所建议的内容”(`services.py`)与“实际存在的内容”(`banner.py`)区分开来,这正是真实评估所关注的区别——端口号并不能证明正在监听什么。
- **最小破坏性扫描**:限制并发和使用超时反映了现实世界中的担忧,即激进的扫描可能会降低甚至击垮您正在测试的目标。
- **I/O 密集型并发**:理解*为什么*使用线程(不仅仅是“使用线程”)能在存在 Python GIL 的情况下依然加速受网络限制的工作负载。
## 未来改进
为了在投入的时间内保持范围的诚实性,本次刻意未包含这些内容,但它们是自然的下一步:
- **UDP 扫描** —— 一种根本上不同的技术(没有握手来确认状态),值得单独进行仔细实现
- **扩展的/社区服务表** 或可选的 `/etc/services` 集成
- 针对识别出的 Banner/版本进行 **CVE 查找**(例如,查询漏洞数据库)——这是一个真正的功能,但在范围上是一个完全独立的项目
- **结构化日志记录**(Python 的 `logging` 模块)代替 print 语句,并带有详细级别
- **速率限制 / 隐秘计时选项**,用于对敏感环境进行更谨慎的扫描
- 在现有的 JSON 输出之外提供 **HTML 报告导出**
- **异步重写**(`asyncio`)作为当前线程模型的比较点,以实现更低开销的更高并发
## 免责声明
此工具仅用于教育目的以及评估您拥有或明确授权测试的系统。未经授权扫描网络或系统可能是非法的。作者不对滥用行为负责。
## 许可证
MIT — 见 [LICENSE](LICENSE)。
标签:DNS查询工具, Python, TCP/IP, 插件系统, 无后门, 端口扫描器, 网络安全, 逆向工具, 隐私保护