assassin-marcos/portwave

GitHub: assassin-marcos/portwave

一款基于 async Rust 的自适应混合协议端口扫描器,集成横幅抓取、TLS 嗅探与 httpx/nuclei 侦察流水线,解决大规模 IPv4/IPv6 端口发现与后渗透关联的效率问题。

Stars: 1 | Forks: 0

# portwave **超高速混合 IPv4 / IPv6 端口扫描器,具备自适应并发、横幅抓取、TLS 嗅探,以及内置的 httpx + nuclei 侦察流水线 —— 使用 async Rust 编写。** [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![Rust](https://img.shields.io/badge/rust-stable-orange.svg)](https://www.rust-lang.org/) [![Platform](https://img.shields.io/badge/platform-linux%20%7C%20macos%20%7C%20windows-lightgrey.svg)]() [![Made for bug bounty](https://img.shields.io/badge/built%20for-bug%20bounty-red.svg)]() ## 为什么选择 portwave? | | masscan | rustscan | naabu | **portwave** | |---|---|---|---|---| | IPv4 扫描 | ✅ | ✅ | ✅ | ✅ | | IPv6 扫描 | ⚠️ | ⚠️ | ✅ | ✅ | | 自适应并发 | ❌ | ❌ | ❌ | ✅ | | 横幅抓取 + 协议分类 | ❌ | ❌ | 部分 | ✅ | | 非 443 端口的 TLS 嗅探 | ❌ | ❌ | ❌ | ✅ | | 崩溃 / Ctrl+C 后恢复 | ❌ | ❌ | ❌ | ✅ | | 内置 httpx + nuclei 流水线 | ❌ | 通过插件 | 通过流水线 | ✅ | | 每协议 nuclei 标签 | ❌ | ❌ | ❌ | ✅ | | 结构化的 `scan_summary.json` | ❌ | ❌ | 部分 | ✅ | | 单一静态二进制文件 | ✅ | ✅ | ✅ | ✅ | ## 功能特性 - **两阶段扫描** — 快速 TCP 发现(默认 600 ms 超时),随后对每个命中点进行被动读取 + HTTP 探测 + 可选的 TLS ClientHello。 - **自适应并发控制器** — 每 2 秒观察超时比例并自动缩小/扩大工作线程池,无需手动调节线程。 - **MPMC 工作队列(通过 `flume`)** — 固定工作线程池(内存占用为 `O(线程数)`,而非 `O(IP数 × 端口数)`)。 - **基于横幅的协议分类器** — 支持 SSH、SMTP、FTP、POP3、IMAP、HTTP、TLS 等协议识别。 - **任意端口的 TLS 嗅探** — 检测 8443 / 9443 或任意自定义端口上的 TLS,并自动为 nuclei 生成 `https://`。 - **恢复机制** — 仅追加写入的 `open_ports.jsonl` 使得重新运行时跳过已知开放端口。 - **优雅的 Ctrl+C 处理** — 排空工作线程并刷新输出后再退出。 - **进度条 + ETA(通过 `indicatif`)**;当探测量超过 10 M 时自动启用旋转加载动画。 - **轮询跨子网** — 跨输入 CIDR 轮询 IP,避免单网段被压测。 - **跳过 IPv4 广播/网络地址** 自动跳过广播地址和网络地址。 - **httpx + nuclei 集成** — 可选按协议打标签启用 nuclei,支持自定义并发与速率限制,可选路径探测。 - **结构化输出** — 生成 `open_ports.jsonl`、`scan_summary.json`,以及传统的 `targets.txt` / `nuclei_targets.txt`。 ## 安装 portwave 运行于 **Linux、macOS 和 Windows**。请选择对应系统的安装方式。 ### Linux / macOS — 一键安装 ``` git clone https://github.com/assassin-marcos/portwave cd portwave bash install.sh ``` 安装程序会: 1. 检测或提示安装 Rust(通过 `rustup`)。 2. 自动检测 `httpx` / `nuclei`(检查 `$PATH`、`~/go/bin`、Homebrew 路径(Apple Silicon 为 `/opt/homebrew/bin`,Intel 为 `/usr/local/bin`)以及 `~/.local/bin`)。 3. 提示选择:扫描输出目录、端口文件、httpx/nuclei 路径、安装前缀。直接回车接受所有默认值。 4. 构建发布二进制文件。 5. 复制到首个可写路径:`~/.local/bin`、`/opt/homebrew/bin`(macOS Apple Silicon)、`/usr/local/bin`。 6. 在 `~/.config/portwave/config.env` 中保存你的选择。 7. 运行 `portwave --version` 进行验证。 非交互模式(静默接受所有默认值): ``` NONINTERACTIVE=1 bash install.sh ``` ### Windows — 一键安装(PowerShell) 从 **提升权限的 PowerShell 窗口**(或普通用户 PowerShell 进行用户级安装)执行: ``` git clone https://github.com/assassin-marcos/portwave cd portwave powershell -ExecutionPolicy Bypass -File .\install.ps1 ``` PowerShell 安装程序会: 1. 检测或提示下载 `rustup-init.exe` 并安装 Rust。 2. 自动检测 `httpx.exe` / `nuclei.exe`(检查 `$PATH`、`%USERPROFILE%\go\bin`、`%USERPROFILE%\.local\bin`、`%ProgramFiles%\{tool}`)。 3. 提示选择:扫描输出目录(默认 `%USERPROFILE%\scans`)、端口文件、httpx/nuclei 路径、安装前缀(默认 `%USERPROFILE%\.local\bin`)。 4. 使用 `cargo build --release` 构建。 5. 复制 `portwave.exe` 到安装前缀。 6. 在 `%APPDATA%\portwave\config.env` 中保存配置。 7. 提示将安装前缀加入用户 `PATH`。 非交互模式: ``` $env:NONINTERACTIVE = '1' powershell -ExecutionPolicy Bypass -File .\install.ps1 ``` ### 手动安装(无需安装器,任意系统) ``` # build cargo build --release # Linux / macOS install -m 0755 target/release/portwave ~/.local/bin/ # or /usr/local/bin mkdir -p ~/.local/share/portwave/ports cp ports/portwave-top-ports.txt ~/.local/share/portwave/ports/ mkdir -p ~/.config/portwave cp .env.example ~/.config/portwave/config.env $EDITOR ~/.config/portwave/config.env # Windows (PowerShell) Copy-Item target\release\portwave.exe $env:USERPROFILE\.local\bin\ New-Item -ItemType Directory -Force $env:LOCALAPPDATA\portwave\ports | Out-Null Copy-Item ports\portwave-top-ports.txt $env:LOCALAPPDATA\portwave\ports\ New-Item -ItemType Directory -Force $env:APPDATA\portwave | Out-Null Copy-Item .env.example $env:APPDATA\portwave\config.env notepad $env:APPDATA\portwave\config.env ``` ### 卸载 ``` bash uninstall.sh # Linux / macOS powershell -ExecutionPolicy Bypass -File .\uninstall.ps1 # Windows ``` ### 更新到最新版本 一旦安装 **v0.5.1 或更高版本**,更新只需一条命令,无需克隆源码、无需重建、无需 Rust 工具链: ``` portwave --update # download + replace the running binary portwave --check-update # just print whether a newer release exists ``` 其工作原理:从 [GitHub Releases](https://github.com/assassin-marcos/portwave/releases) 页面拉取适用于你操作系统与架构的预构建二进制文件(由 CI 在每次标签发布时构建),并原子替换当前可执行文件。 启动横幅会在有更新时提醒你(最多每 24 小时检查一次,超时 3 秒,避免慢速网络阻塞扫描)。可通过 `--no-update-check` 禁用单次检查,或全局禁用: ``` export PORTWAVE_NO_UPDATE_CHECK=1 ``` **从 v0.5.0 首次升级**(尚不支持 `--update`)需要一次性手动步骤: ``` cd /path/to/portwave-clone git pull bash install.sh # or .\install.ps1 on Windows ``` 之后所有更新均可使用 `portwave --update`。 **macOS Gatekeeper 提示**:通过 `--update` 下载的二进制文件未进行公证。如 macOS 拒绝运行,请执行: ``` xattr -d com.apple.quarantine "$(command -v portwave)" ``` ### 平台相关说明 | 平台 | 文件描述符限制调整 | 配置文件位置 | |---|---|---| | Linux | 启动时调用 `setrlimit(RLIMIT_NOFILE, 50000)` | `~/.config/portwave/config.env` | | macOS | 启动时调用 `setrlimit(RLIMIT_NOFILE, 50000)` | `~/.config/portwave/config.env` | | Windows | 无操作(Windows 不以文件描述符限制套接字) | `%APPDATA%\portwave\config.env` | 在 Linux 上,若发行版的用户限制低于 50000,可能还需要在 Shell 中执行 `ulimit -n 50000`(检查 `/etc/security/limits.conf`)。 ### 可选依赖(完整流水线所需) - [`httpx`](https://github.com/projectdiscovery/httpx)(ProjectDiscovery)— HTTP 指纹识别 - [`nuclei`](https://github.com/projectdiscovery/nuclei) — 漏洞扫描 即使没有它们,portwave 仍可运行(加上 `--no-httpx --no-nuclei`),仅不会执行扫描后的增强处理。 ## 快速开始 ``` # 扫描单个 /24 并运行完整流水线 portwave acme_corp 203.0.113.0/24 # 多个 CIDR(混合 v4 / v6) portwave acme_corp "203.0.113.0/22,198.51.100.0/24,2001:db8::/120" # 仅端口发现,跳过 httpx + nuclei portwave acme_corp 203.0.113.0/24 --no-httpx --no-nuclei # 自定义端口列表 portwave acme_corp 203.0.113.0/24 --port-file /path/to/ports.txt # 本地主机冒烟测试 portwave demo 127.0.0.1/32 --no-httpx --no-nuclei ``` ## 完整用法 ``` portwave [OPTIONS] ``` | 参数 | 说明 | |---|---| | `` | 输出根目录下的子目录(例如 `acme_corp`、`bounty_target_01`) | | `` | 逗号分隔的 CIDR 列表,支持 IPv4 或 IPv6(`203.0.13.0/24,2001:db8::/120`) | | 标志 | 默认值 | 用途 | |---|---|---| | `--port-file ` | 内置 427 端口列表 | 逗号/空白分隔的端口列表 | | `-t, --threads ` | `4000` | 最大并发探测数(自适应控制器可能缩小) | | `--timeout-ms ` | `600` | 阶段 A(发现)连接超时 | | `--enrich-timeout-ms ` | `1500` | 阶段 B(横幅/TLS)连接超时 | | `--retries ` | `0` | 仅阶段 A 超时重试次数 | | `--output-dir ` | 配置文件中设定 | 基础输出目录 | | `--httpx-threads ` | `150` | httpx 并发数 | | `--httpx-paths ` | (未设置) | httpx 额外探测路径(如 `/actuator,/.git/HEAD`) | | `--httpx-follow-redirects` | 关闭 | 跟随 httpx 重定向 | | `--nuclei-concurrency ` | `50` | nuclei 的 `-c` 参数 | | `--nuclei-rate ` | `200` | nuclei 的 `-rl` 速率限制 | | `--tags-from-banner` | 关闭 | 根据检测到的协议为 nuclei 传递 `-tags` | | `--no-httpx` | 关闭 | 跳过 httpx 步骤 | | `--no-nuclei` | 关闭 | 跳过 nuclei 步骤 | | `--no-banner` | 关闭 | 跳过阶段 B 增强 | | `--no-tls-sniff` | 关闭 | 跳过非 443 端口的 TLS 嗅探 | | `--no-adaptive` | 关闭 | 禁用自适应并发控制器 | | `--no-resume` | 关闭 | 不加载 `open_ports.jsonl` 作为跳过集合 | ## 实际使用示例 ### 漏洞赏金范围的全面扫描(/20 或更大网段) ``` portwave acme_corp "203.0.113.0/20" \ --threads 3000 \ --timeout-ms 800 --retries 1 \ --enrich-timeout-ms 2000 \ --tags-from-banner \ --httpx-threads 200 \ --nuclei-concurrency 40 --nuclei-rate 150 ``` ### 小规模高精度资产列表 ``` portwave vip "1.2.3.0/28" \ --threads 500 \ --timeout-ms 1500 --retries 2 \ --enrich-timeout-ms 3000 ``` ### 大规模 IPv6 范围 — 启用旋转加载动画 ``` portwave v6_probe "2001:db8::/96" \ --threads 6000 --timeout-ms 500 --retries 0 ``` ### 恢复被中断的扫描 ``` # 使用相同的文件夹名称重新运行 — replay open_ports.jsonl。 portwave acme_corp 203.0.113.0/24 # 强制全新扫描: portwave acme_corp 203.0.113.0/24 --no-resume ``` ### 路径探测以定位框架端点 ``` portwave acme_corp 203.0.113.0/24 \ --httpx-paths "/actuator,/.git/HEAD,/server-status,/.env,/admin,/api/v1" ``` ### 仅执行发现,不进行增强,不使用流水线 ``` portwave acme_corp 203.0.113.0/24 --no-httpx --no-nuclei --no-banner ``` ## 输出产物 每次扫描的结果写入 `//` 目录下: | 文件 | 格式 | 用途 | |---|---|---| | `targets.txt` | 每行 `ip:port` | 原始开放端点,供需要 `IP:PORT` 格式的工具使用 | | `nuclei_targets.txt` | URL + `ip:port` | `http://`、`https://` 或 `ip:port` — 直接可用于 nuclei | | `open_ports.jsonl` | 每行一个 JSON | 结构化数据:`{ip, port, rtt_ms, tls, protocol, banner}` | | `scan_summary.json` | 单个 JSON | `{folder, duration_ms, attempts, timeouts, open, by_port, by_protocol, ranges, ports}` | | `httpx_results.txt` | httpx 默认输出 | 状态码、长度、重定向、标题 | | `nuclei_results.txt` | nuclei 默认输出 | 漏洞发现结果 | `open_ports.jsonl` 示例: ``` {"ip":"203.0.113.42","port":8443,"rtt_ms":84,"tls":true,"protocol":"tls","banner":null} {"ip":"203.0.113.42","port":22,"rtt_ms":71,"tls":false,"protocol":"ssh","banner":"SSH-2.0-OpenSSH_8.9p1"} ``` `scan_summary.json` 示例: ``` { "folder": "acme_corp", "duration_ms": 142318, "attempts": 109567, "timeouts": 412, "open": 87, "by_port": { "80": 22, "443": 19, "22": 14, "8080": 11, "8443": 9 }, "by_protocol": { "http": 41, "ssh": 14, "tls": 18, "unknown": 14 }, "ranges": ["203.0.113.0/24"], "ports": 427 } ``` ## 配置 portwave 按以下优先级查找路径: 1. CLI 标志(`--output-dir`、`--port-file`、…) 2. 环境变量(`PORTWAVE_OUTPUT_DIR`、`PORTWAVE_PORTS`) 3. `~/.config/portwave/config.env`(由 `install.sh` 创建) 4. 内置回退值(输出目录为 `./scans`,端口列表为内置列表) `~/.config/portwave/config.env` 使用简单的 `KEY=VALUE` 格式。请参考 `.env.example`。 ``` PORTWAVE_OUTPUT_DIR=/home/user/scans PORTWAVE_PORTS=/home/user/.local/share/portwave/ports/portwave-top-ports.txt PORTWAVE_HTTPX_BIN=/home/user/go/bin/httpx PORTWAVE_NUCLEI_BIN=/home/user/go/bin/nuclei ``` ## 性能建议 - **提高文件描述符限制** — portwave 启动时会调用 `setrlimit(RLIMIT_NOFILE, 50000)`,但你的 Shell 也可能需要执行 `ulimit -n 50000`。 - **降低 `--timeout-ms`** — 在局域网或本地目标上使用 `200`–`400` ms 即可。 - **提高 `--threads`** — 仅在你有足够上行带宽时提高;自适应控制器会在饱和时自动限流。 - **使用 `--retries 0`** — 首次扫描时使用,随后在同一文件夹中再次扫描时使用 `--retries 2` 以重新检查超时(恢复会跳过已确认开放的端口)。 - **`--tags-from-banner`** 可将 nuclei 运行时间缩短 30–60%,适用于混合端口扫描。 ## 工作原理(简述) ``` ┌────────────────────────────┐ CIDR + ports │ Producer: round-robin IPs │ ──────────▶ │ across subnets, push into │ │ a bounded flume MPMC queue │ └──────────────┬─────────────┘ │ SocketAddr ┌───────────▼────────────┐ ┌──────────────┐ │ N Phase-A workers │ │ Adaptive │ │ TCP connect + timeout │◀────────┤ monitor │ │ + optional retry │ │ (timeout %) │ └───────────┬────────────┘ └──────────────┘ │ hits (mpsc) ┌───────────▼────────────┐ │ Collector → Phase B │ │ banner grab, HTTP probe│ │ TLS ClientHello sniff │ └───────────┬────────────┘ │ OpenPort ┌───────────▼────────────┐ │ Writer: dedup + sort + │ │ BufWriter to targets/ │ │ nuclei_targets/jsonl │ └───────────┬────────────┘ │ ┌───────────▼────────────┐ │ httpx → httpx_results │ │ nuclei → nuclei_results│ └────────────────────────┘ ``` ## 常见问题 **portwave 是否执行 SYN 扫描?** 目前尚未支持 — portwave 使用完整的 TCP 连接。SYN 扫描需要原始套接字(需要 root 权限或特定能力)。若要扫描 `/16` 及以上大范围地址,可将 portwave 与 [`masscan`](https://github.com/robertdavidgraham/masscan) 结合使用,先用 masscan 发现,再由 portwave 进行增强。 **为何检测到 22 端口但横幅为空?** SSH 应立即发送其横幅,因此应看到 `SSH-2.0-...`。若未看到,可能是服务器启用了 TCP 限制或响应较慢;可尝试调高 `--enrich-timeout-ms`。 **portwave 在自己的网络上运行安全吗?** 是的 — 这正是本地烟雾测试的用途。未经许可对第三方基础设施进行扫描 **可能存在法律风险**,仅应在授权范围内使用(漏洞赏金范围、授权测试、自己的资产)。作者不对滥用行为承担任何责任。 **能否在 Python / Go 中使用?** 可以解析 `scan_summary.json` 和 `open_ports.jsonl` — 两者均为稳定的标准结构化格式。 **是否支持 macOS / Windows?** Linux 是主要目标。代码基本可移植;`raise_fd_limit()` 使用 libc 的 `setrlimit`,在 Windows 上无法工作。欢迎提交 PR。 ## 搜索关键词(寻找此类工具的用户) 端口扫描器、端口扫描、快速端口扫描器、Rust 端口扫描器、异步端口扫描器、IPv6 端口扫描器、网络扫描器、渗透测试、漏洞赏金、侦察、侦察流水线、进攻性安全、红队、红队演练、nuclei 集成、httpx 集成、masscan 替代品、rustscan 替代品、naabu 替代品、横幅抓取器、TLS 嗅探器、CIDR 扫描器、TCP 扫描器、服务识别。 ## 许可证 MIT — 参见 [LICENSE](LICENSE)。 ## 免责声明 portwave 是一个安全研究工具。**仅在你拥有或获得明确授权的系统上使用**。未经授权的扫描可能违反当地法律。作者不承担任何滥用责任。
标签:Banner抓取, Flume, Httpx集成, IPv4, IPv6, MPMC队列, Nuclei联动, PowerShell, SEO: Rust安全工具, SEO: 端口扫描器, SEO: 高速扫描器, TLS嗅探, 协议识别, 可视化界面, 异步Rust, 扫描摘要, 数据统计, 有状态扫描, 端口扫描, 自适应并发, 运行时操纵, 通知系统, 静态二进制, 高性能扫描