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绕过, 目录遍历, 程序破解, 端口扫描, 端口探测, 网络安全, 网络延迟测量, 网络扫描器, 通知系统, 通知系统, 隐私保护, 高性能网络