Zoel-Manchon/pyscan

GitHub: Zoel-Manchon/pyscan

一个采用六边形架构的模块化端口扫描器,支持工控协议识别和网络资产发现,核心设计目标是高可扩展性。

Stars: 0 | Forks: 0

# Pyscan 一个微型、模块化、**六边形**架构的端口扫描器 —— 一个专为扩展而生的 mini-Nmap。 ![python](https://img.shields.io/badge/python-3.11+-blue) ![license](https://img.shields.io/badge/license-MIT-green) ![tests](https://img.shields.io/badge/tests-41%20passing-brightgreen) 这个项目的重点不在于扫描器本身 —— 一个 TCP connect 扫描大概只有 30 行代码。 重点在于**架构**:一个清晰的端口和适配器布局,每一种新的 扫描技术、输出格式和发现方法都是即插即用的,并且核心 引擎永远不需要改动。 ## 目前可用的功能 - **异步 TCP connect 扫描** —— 无需特权,并发受限,速度快 - **Banner 抓取** —— 读取服务在连接时主动提供的信息,外加 HTTP `HEAD` 探测,以诱使 Web 服务器返回 `Server:` 头 - **服务 / 版本检测** —— 纯粹的、由 regex 驱动的指纹引擎 (`OpenSSH 9.6p1`, `nginx 1.24.0`, ...) - **主机发现 + CIDR 扫描** —— 对整个范围进行 TCP-ping,建立存活主机 及其服务的清单 - **Modbus/TCP 识别** —— 只读的 OT 资产发现 (厂商 / 产品 / 固件),**仅限模拟器** - **输出** —— 美观的 `rich` 终端表格 *以及* 机器可读的 JSON - **41 个测试**,主要是纯单元测试,无需网络 ![pyscan demo](https://static.pigsec.cn/wp-content/uploads/repos/cas/9d/9d466264bd7f51d85040241e44d8809b54682de051d57033ddf1515bd26cd999.gif) ## 快速开始 ``` pip install -e ".[dev]" # or: make dev pytest -q # 41 passing ``` ``` # 单个 host 的深度扫描 pyscan scan scanme.nmap.org -p 22,80,443 # 发现某个范围内的 live host 并将其清点 pyscan sweep 192.168.1.0/24 pyscan sweep 192.168.1.0/24 --detail # + per-host port tables pyscan sweep 10.0.0.0/28 --json net.json # machine-readable inventory # Modbus/TCP 设备识别 — 仅限 SIMULATORS / 实验室设备 pyscan scan 127.0.0.1 -p 502 --type modbus pyscan version # the snake pyscan strategies # list scan techniques ``` ## 架构 依赖关系**向内**指向。领域模型对 socket、 终端或 Typer 一无所知。适配器依赖于领域模型的接口,绝不能反过来 —— 因此外层的任何内容都可以被独立替换。 ``` flowchart TB CLI["cli · Typer + snake banner"] subgraph APP["application"] SCAN["ScanService"] SWEEP["SweepService"] end subgraph DOMAIN["domain · pure core"] MODELS["models · targets · port_spec
well_known · fingerprint"] PORTS["ports.py — interfaces
ScanStrategy · HostDiscovery
ResultSink · NetworkSink"] end subgraph ADAPTERS["adapters · all I/O"] STRAT["strategies · tcp_connect"] DISC["discovery · tcp_ping"] OUT["output · table / json / network_*"] end CLI --> SCAN CLI --> SWEEP SWEEP --> SCAN SCAN --> PORTS SWEEP --> PORTS STRAT -. implements .-> PORTS DISC -. implements .-> PORTS OUT -. implements .-> PORTS SCAN --> MODELS CLI --> STRAT CLI --> DISC CLI --> OUT ``` 扫描 pipeline 将**探测** (I/O) 与**识别** (纯逻辑) 分开,因此每个阶段都可以独立测试和替换: ``` flowchart LR A["CIDR / host"] --> B["expand_targets
(pure)"] B --> C["discover
TCP-ping"] C --> D["scan up hosts
per-port probe (I/O)"] D --> E["enrich
fingerprint (pure)"] E --> F["render
inventory · table / JSON"] ``` ## 项目布局 ``` src/pyscan/ ├── domain/ pure core — no I/O │ ├── models.py value objects + ScanReport / NetworkReport │ ├── ports.py the 4 interfaces (the hexagon boundary) │ ├── targets.py CIDR / IP / host expansion │ ├── port_spec.py "1-1024,8080" parser │ ├── fingerprint.py banner -> service/product/version │ └── well_known.py port -> service map ├── application/ │ ├── scan_service.py single-host orchestration + enrichment │ └── sweep_service.py discovery + per-host scan + inventory ├── adapters/ all I/O lives here │ ├── strategies/ tcp_connect (+ registry) │ ├── discovery/ tcp_ping │ └── output/ table · json · network_table · network_json └── cli/ main (Typer) · banner (snake) ``` ## 如何扩展 | 想要添加… | 操作方式 | 是否涉及引擎? | |---|---|---| | 扫描技术 (SYN, UDP) | 在 `adapters/strategies/` 中新建文件,`@register("name")` | 否 | | 输出格式 (CSV, SQLite) | 实现 `ResultSink` / `NetworkSink` | 否 | | 发现方法 (ICMP, ARP) | 实现 `HostDiscovery` | 否 | | 对新产品的检测 | 在 `fingerprint.py` 中添加一行 regex | 否 | ## 路线图 - [x] TCP connect 扫描,异步并发,表格 + JSON - [x] Banner 抓取 + HTTP 探测 - [x] 服务 / 版本指纹识别 - [x] 主机发现 + CIDR 扫描 + 清单 - [x] Modbus/TCP 识别(只读)—— 仅限模拟器 - [x] IEC 60870-5-104 识别(只读)—— 仅限模拟器 - [x] S7comm 识别(只读)—— 仅限模拟器 - [ ] SYN / 半开扫描 (raw sockets,需特权) - [ ] SYN / 半开扫描 (raw sockets,需特权) - [ ] UDP 扫描 - [ ] 将此骨架复用于数据包嗅探器 (带 Textual TUI) ## Docker 无需本地 Python 环境即可运行: ``` docker build -t pyscan . docker run --rm pyscan scan scanme.nmap.org -p 22,80,443 docker run --rm pyscan sweep 192.168.1.0/24 ``` 该镜像*即是*命令(pyscan 是 entrypoint)。这是一个 CLI 工具,因此 特意没有进行编排 —— 它没有需要扩展的长期运行服务, 那是 Kubernetes 的职责。 ## 关于权限的说明 `tcp-connect` 扫描和 `tcp-ping` 发现使用普通的内核 socket —— **不需要 root 权限**。未来的 SYN 扫描会构造 raw 数据包,*将*需要 提升的权限;这是操作系统对 raw socket 的限制,而不是 Python 的。 ## 许可证 MIT —— 见 [LICENSE](LICENSE)。
标签:Python, 安全规则引擎, 工控协议, 插件系统, 数据统计, 无后门, 架构设计, 端口扫描, 网络扫描器, 计算机取证, 请求拦截, 逆向工具