NullRabbitLabs/limpet-trs

GitHub: NullRabbitLabs/limpet-trs

基于 eBPF/XDP 内核旁路技术的高精度 TCP SYN 扫描器,专注于端口发现和纳秒级 RTT 测量,输出 ML 就绪的时序数据。

Stars: 0 | Forks: 0

# Limpet TRS 具备 eBPF/XDP 内核旁路计时功能的高精度网络扫描器。发送原始 TCP SYN 包,通过 BPF maps 在内核边界捕获响应,并以纳秒级分辨率测量往返时间。 Limpet 并不是为了替代 nmap 的服务指纹识别——它只专注做好一件事:**告诉你哪些端口是开放的,以及它们响应所花费的时间**。 ``` $ sudo limpet 192.168.1.1 PORT STATE RTT 22/tcp open 1.2ms 80/tcp open 0.8ms 443/tcp open 0.9ms 8080/tcp filtered — Scanned 1000 ports in 2.1s ``` TRS 代表什么?时间共振扫描器 (Temporal Resonance Scanner)。你是第一次听说这个名字吧。 ## 功能特性 - **SYN 扫描器** — 原始套接字发送端,不建立连接 - **XDP/BPF 计时** — 来自内核旁路路径的逐包时间戳;当 XDP 不可用时,回退到用户态 `gettimeofday` - **隐蔽 pacing** — 可配置的包间延迟,以避免触发速率限制 - **ML 就绪输出** — 计时样本(不仅仅是单个 RTT)、均值/p50/p90 统计数据,以及每个端口的 64 维嵌入向量 - **JSON 输出** — 适用于流水线的机器可读结果 - **MCP server** — 通过 Model Context Protocol 向 AI 助手暴露扫描和计时工具 - **HTTP server** (`limpet-server`) — 用于编排系统的 REST API ## 系统要求 | 要求 | 说明 | |-------------|-------| | Linux kernel ≥ 5.11 | 用于 BPF ring buffers;在较旧的内核上 XDP 计时会优雅地降级到用户态 | | `NET_RAW` + `NET_ADMIN` capabilities | 原始套接字 SYN 扫描所需 | | `CAP_BPF` + `CAP_SYS_ADMIN` | XDP/BPF 计时所需(用户态回退不需要) | | 裸机或 KVM 虚拟机 | AF_XDP 需要真实的网卡驱动;Docker Desktop (macOS/Windows) 将回退到用户态计时 | | Root 或 `sudo` | 最简单的方式;或者使用 `setcap` 授予权限 | **不适用于:** macOS, Windows, Docker Desktop(指 BPF 功能——CLI 可以构建,但计时会回退到用户态)。 ## 安装 ### 从源码构建 ``` # BPF 构建依赖 (Debian/Ubuntu) sudo apt-get install llvm clang libbpf-dev libelf-dev linux-libc-dev # 如需安装 Rust curl https://sh.rustup.rs | sh git clone https://github.com/nullrabbit/limpet cd limpet cargo build --release # 安装 sudo cp target/release/limpet /usr/local/bin/ ``` ### Capabilities(无需以 root 身份运行) ``` sudo setcap 'cap_net_raw,cap_net_admin,cap_bpf,cap_sys_admin+eip' /usr/local/bin/limpet ``` ## CLI 用法 ### 快速扫描(前 1000 个端口) ``` sudo limpet 203.0.113.1 ``` ### 指定端口 ``` sudo limpet 203.0.113.1 --ports 22,80,443,8080-8090 ``` ### 全端口扫描 ``` sudo limpet 203.0.113.1 --ports 1-65535 ``` ### JSON 输出 ``` sudo limpet scan 203.0.113.1 --ports top-1000 --output json | jq '.port_results[] | select(.state == "Open")' ``` ### 隐蔽扫描(慢速 pacing) ``` sudo limpet scan 203.0.113.1 --stealth slowest --ports top-1000 ``` 可用的隐蔽配置:`slowest`, `slow`, `normal` (默认), `fast`, `turbo` ### 单端口 TCP RTT 计时 ``` sudo limpet time 203.0.113.1 --port 443 --samples 10 ``` ``` { "target_host": "203.0.113.1", "target_port": 443, "samples": [1210.3, 1184.7, 1241.2, 1193.1, 1216.8, 1201.4, 1228.0, 1210.1, 1184.3, 1241.7], "precision_class": "xdp", "stats": { "mean": 1211.2, "std": 20.3, "p50": 1210.3, "p90": 1241.2 } } ``` 样本单位为 **微秒**。 ### MCP server(用于 AI 助手) ``` limpet --mcp ``` 通过 stdio 暴露 `scan_ports` 和 `measure_timing` 作为 MCP 工具。添加到你的 AI 助手的工具配置中,即可通过自然语言运行网络扫描。 ## 库用法 ``` use limpet::{PortSpec, PortState, TimingRequest}; use limpet::scanner::syn_sender::SynScanner; use limpet::scanner::collector::DiscoveryCollector; use limpet::timing::collect_timing_samples; // Port discovery let scanner = SynScanner::new("eth0")?; let collector = DiscoveryCollector::new(); let spec = PortSpec::TopN(1000); let results = scanner.scan("203.0.113.1".parse()?, spec, collector).await?; for port in results.iter().filter(|p| p.state == PortState::Open) { println!("{} {:?} {:.2}ms", port.port, port.state, port.timing_ns as f64 / 1e6); } // Single-port RTT timing (10 samples) let req = TimingRequest { target_host: "203.0.113.1".to_string(), target_port: 443, sample_count: 10, timeout_ms: 5000, banner_timeout_ms: None, }; let result = collect_timing_samples(&req).await?; println!("mean RTT: {:.2}ms", result.stats.mean / 1000.0); // samples are µs ``` ## HTTP 服务器 (`limpet-server`) `limpet-server` 通过 HTTP 暴露扫描引擎,用于分布式扫描流水线。编排器直接调用它,而不是发布到消息队列。 ``` # 构建 cargo build --release --bin limpet-server # 运行 (需要 caps 或 root) sudo PORT=8888 ./target/release/limpet-server ``` ### 环境变量 | 变量 | 默认值 | 描述 | |----------|---------|-------------| | `PORT` | `8888` | HTTP 监听端口 | | `LIMPET_INTERFACE` | 自动检测 | 用于 XDP 的网络接口 | | `WORKER_NODE` | 主机名 | 在所有响应中报告 | | `RUST_LOG` | `info` | 日志级别 (`debug`, `info`, `warn`, `error`) | ### `GET /v1/health` ``` curl http://localhost:8888/v1/health ``` ``` { "status": "ok", "worker_node": "scanner-1", "source_ip": "10.0.1.5" } ``` ### `POST /v1/discovery` ``` curl -X POST http://localhost:8888/v1/discovery \ -H 'Content-Type: application/json' \ -d '{ "request_id": "req-001", "target_ip": "203.0.113.1", "ports": { "type": "top-n", "value": 1000 }, "timeout_ms": 30000 }' ``` ``` { "request_id": "req-001", "target_ip": "203.0.113.1", "ports_scanned": 1000, "port_results": [ { "port": 22, "state": "Open", "timing_ns": 1204000 }, { "port": 80, "state": "Open", "timing_ns": 823000 }, { "port": 443, "state": "Open", "timing_ns": 901000 } ], "actual_duration_ms": 2140, "scanner_backend": "xdp", "source_ip": "10.0.1.5", "worker_node": "scanner-1" } ``` ### `POST /v1/timing` ``` curl -X POST http://localhost:8888/v1/timing \ -H 'Content-Type: application/json' \ -d '{ "request_id": "timing-001", "target_host": "203.0.113.1", "target_port": 22, "sample_count": 5, "timeout_ms": 10000 }' ``` ``` { "request_id": "timing-001", "target_host": "203.0.113.1", "target_port": 22, "samples": [1204.3, 1198.7, 1211.2, 1203.1, 1206.8], "precision_class": "xdp", "stats": { "mean": 1204.8, "std": 4.3, "p50": 1204.3, "p90": 1211.2 }, "banner": "U1NILTIuMC1PcGVuU1NIXzguOQ==", "worker_node": "scanner-1" } ``` `banner` 是从远程主机发送的第一个数据包中的原始字节,经 base64 编码。样本单位为 **微秒**。 ## 限制 **平台** - 仅限 Linux。BPF/XDP 路径需要内核 ≥ 5.11 才能使用 ring buffers。较旧的内核会自动回退到用户态计时。 - AF_XDP 需要支持 XDP 的网卡驱动。Virtio-net (KVM/QEMU) 可用。VMware vmxnet3 和某些云 hypervisor 网卡不支持。 - macOS/Windows 上的 Docker Desktop:CLI 可以构建并运行,但 BPF 程序无法加载——计时会回退到用户态。 **扫描** - **无服务检测** — limpet 识别开放端口并收集 RTT 样本。`banner` 字段包含服务器首次响应包中的原始字节,但不进行协议解析。 - **仅限 TCP** — 无 UDP 扫描。 - **仅限 IPv4** — 原始套接字发送端不支持 IPv6。 - 在 `turbo` pacing 下的大范围端口扫描会产生大量流量,可能会触发防火墙速率限制或 IDS 告警。使用 `--stealth slowest` 进行静默扫描。 - `filtered` 结果意味着在超时时间内未收到响应——端口可能被防火墙屏蔽、速率限制,或者主机已宕机。 **计时精度** - XDP 时间戳在网卡接收时记录,而非在应用程序代码中。这提供了包含网卡驱动开销在内的真实线路延迟,而非软件调度抖动。 - 用户态回退 (`precision_class: "userspace"`) 在负载下有 ±50–200µs 的抖动——精度足以进行粗略指纹识别,但不适用于亚毫秒级的抖动分析。 - RTT 样本包含完整的 TCP 握手(SYN → SYN-ACK)。这是故意的:握手延迟是指纹识别的信号。 **权限** - 原始套接字扫描需要 `NET_RAW` 和 `NET_ADMIN`。BPF 计时另外需要 `CAP_BPF` 和 `CAP_SYS_ADMIN`。没有非特权模式。 **不能替代** - **nmap** — 无 OS 检测,无脚本引擎,无服务版本检测 - **masscan** — 未针对互联网规模扫描进行优化;专为单主机或小范围设计 - **Wireshark / tcpdump** — limpet 不捕获任意流量 ## 项目结构 ``` limpet/ ├── src/ │ ├── lib.rs # Public API — PortState, TimingRequest, TimingResult, re-exports │ ├── main.rs # CLI binary (limpet) │ ├── cli/ # Clap argument parsing + scan/time command runners │ ├── mcp/ # MCP server (scan_ports + measure_timing tools) │ ├── bin/ │ │ └── server.rs # limpet-server HTTP binary (Axum) │ ├── scanner/ │ │ ├── syn_sender.rs # Raw SYN scanner (AF_PACKET / AF_XDP TX) │ │ ├── afxdp_sender.rs # AF_XDP zero-copy sender │ │ ├── collector.rs # BPF map reader — assembles DiscoveryResult │ │ ├── stealth.rs # Pacing profiles (inter-packet delay) │ │ └── mod.rs │ └── timing/ │ ├── xdp.rs # BpfTimingCollector — XDP kernel-bypass timing │ ├── userspace.rs # Fallback: connect(2) + gettimeofday timing │ ├── embeddings.rs # 64-dim feature vector extraction │ ├── stats.rs # Mean / std / percentile helpers │ └── mod.rs └── bpf/ └── timing.bpf.c # eBPF program — per-packet timestamps into ring buffer ``` ## 背景 Limpet 是 [NullRabbit](https://nullrabbit.ai) 平台的开源扫描组件——该平台为验证者基础设施和去中心化网络提供自主防御。 来自 Limpet 的计时嵌入和 ML 就绪输出被输入到 NullRabbit 的专有威胁分析和行为基线系统中。关于自主防御行动背后的治理框架,请参阅: 来自 Limpet 的计时样本可通过 [Minerva-HDN](https://github.com/NullRabbitLabs/minerva-hdn) 进行分析,以检测蜜罐和合成服务。 ## 法律声明 本工具仅用于授权的安全测试、网络管理和研究目的。在扫描任何目标之前,您必须获得网络所有者的明确许可。未经授权的端口扫描可能违反您所在司法管辖区的计算机滥用法律(例如英国的《计算机滥用法 1990》、美国的 CFAA)。作者对滥用行为不承担任何责任。 ## 许可证 MIT
标签:AGPLv3 许可证, C2日志可视化, Docker镜像, Go语言, HTTP服务器, Linux工具, Raw Socket, REST API, RTT, SYN扫描, TCP/IP, XDP, 主动探测, 二进制发布, 人工智能, 内核旁路, 可视化界面, 域名解析, 密码管理, 开源工具, 指纹识别, 插件系统, 数据统计, 用户模式Hook绕过, 目录遍历, 程序破解, 端口扫描, 端口探测, 网络安全, 网络延迟测量, 网络扫描器, 通知系统, 通知系统, 隐私保护, 高性能网络