Packet-Batch/pktbatch-rs
GitHub: Packet-Batch/pktbatch-rs
基于 Rust 与 AF_XDP 的高性能网络数据包生成工具,专为渗透测试、基准测试和网络监控场景设计。
Stars: 5 | Forks: 1
[Packet Batch](https://github.com/Packet-Batch) 是一组用于生成网络数据包的高性能工具。这些工具通常用于渗透测试、基准测试和网络监控。

本仓库是 Packet Batch 的 Rust 实现。虽然 Packet Batch 最初是用 C 语言编写的([`pktbatch-c`](https://github.com/Packet-Batch/pktbatch-c)),但这个 Rust 版本旨在提供更安全、更现代的代码库,同时保持高性能。
也就是说,这里现在将成为 Packet Batch 的主仓库。虽然 `pktbatch-c` 仍将得到维护,但所有新功能和改进都将在这个 Rust 实现中进行开发。C 语言版本将仅接收关键错误修复。
[](https://github.com/Packet-Batch/pktbatch-rs/actions/workflows/build.yml) [](https://github.com/Packet-Batch/pktbatch-rs/actions/workflows/run.yml)
## 🚀 功能
* 使用诸如 [AF_XDP 套接字](https://docs.kernel.org/networking/af_xdp.html) 等技术实现快速数据包生成。
* ⚠️ AF_XDP 支持目前是唯一可用的选项,但未来可能会添加对其他技术(例如 DPDK、AF_PACKET 等)的支持!
* 高度可配置的数据包生成,支持多种协议和自定义 payload。
* 支持主机名和 DNS 查找。
* 支持生成随机的源和目的 IP 地址、端口以及其他头部字段,如 IP 的 TTL 和 ID 字段。
* 监视器模式,显示实时统计数据和接口当前 TX 统计信息的图表。
* 该模式从 NIC 自身检索写入 `/proc/net/dev` 文件的计数器。因此,在监视器模式下显示统计数据应对数据包生成的整体性能产生极小的影响!
* 详细的包生成活动日志记录,包括支持不同的日志级别和日志文件管理。
* 支持执行具有不同配置的多个数据包批次。
* 命令行界面,包含用于覆盖第一批配置的参数,而无需修改磁盘上的配置文件。
## 🚨 实验性
Packet Batch 的 Rust 实现目前处于早期开发阶段,被认为是**实验性的**!话虽如此,我对 Rust 仍然相当陌生,可能存在一些需要解决的错误和性能问题。
然而,从我目前得出的测试结果来看,一切正常,而且性能实际上比 C 语言版本更好!!
这是我计划深入研究的事情。这可能是由于 Rust 版本中 AF_XDP 套接字的设置和使用方式造成的,但我还没抽出时间来验证这一点。
## 🛠️ 构建
### XDP 工具 (LibXDP, LibBPF 等)
你需要安装 [`xdp-tools`](https://github.com/xdp-project/xdp-tools) 及其依赖项,以构建项目的 AF_XDP 版本(目前唯一可用的版本)。我建议遵循[此处](https://github.com/xdp-project/xdp-tutorial/blob/main/setup_dependencies.org)的说明进行操作。
以下是我在基于 Debian 的系统上为设置依赖项而运行的命令:
```
# 安装依赖
sudo apt update
sudo apt install -y clang llvm libelf-dev libpcap-dev build-essential libc6-dev-i386 m4 git
# Clone 并 build xdp-tools
git clone --recursive https://github.com/xdp-project/xdp-tools
cd xdp-tools
# Build 并安装 xdp-tools
make
# 将 xdp-tools 安装到系统。
sudo make install
# 虽然从技术上讲不应该需要,但我总是 build 并安装 LibBPF,它是 `xdp-tools` 内的一个 sub-module。
# 切换到 libbpf 目录。
cd lib/libbpf/src
# Build 并安装 libbpf
make
sudo make install
```
### 项目
安装上述依赖项后,就可以构建主项目了。首先,让我们快速克隆仓库。
```
# Clone repository
git clone https://github.com/Packet-Batch/pktbatch-rs
# 切换到项目目录
cd pktbatch-rs
```
你的系统上**必须**安装 Rust。你可以使用 [`rustup`](https://rustup.rs/) 安装 Rust。安装 Rust 后,你可以使用 Rust 的包管理器和构建系统 Cargo 来构建项目。
```
# 使用 rustup 安装 Rust(如果你还没有安装的话)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 在 release mode 下 build 项目
cargo build --release
```
这将编译项目并在 `target/release` 目录中生成一个可执行文件。
如果你想在整个系统中使用 `pktbatch` 可执行文件而不是使用 `cargo run`,你可以使用 [`install_to_path.sh`](./install_to_path.sh) 脚本将可执行文件复制到 `/usr/bin/` 目录。
```
# 将 pktbatch 安装到 /usr/bin/(已包含在 $PATH 中;需要 sudo)。
./install_to_path.sh
# 现在你可以在终端的任何位置使用 'pktbatch' 了。
sudo pktbatch --help
sudo pktbatch -c ./local.json -i eth0
```
## ⚙️ 用法
构建项目后,你可以运行可执行文件来生成网络数据包。确切的用法将取决于你提供的命令行参数以及主程序的配置文件。
以下是你可以使用的主要命令行参数列表。
| 参数 | 描述 |
| --- | --- |
| `-c, --cfg ` | 配置文件的路径(必需) |
| `-l, --list` | 列出配置设置并退出。 |
| `-w, --watch` | 显示实时统计数据和接口当前 TX 统计信息的图表。 |
| `-h, --help` | 打印帮助信息 |
| `-V, --version` | 打印版本信息 |
## 首批覆盖
你可以传递以下标志来覆盖/设置第一批。这对于使用不同的参数快速运行工具非常有用,而无需修改磁盘上的配置文件。
| 参数 | 描述 |
| --- | --- |
| `-i, --iface ` | 覆盖第一批的网络接口。 |
| `-a, --smac ` | 覆盖第一批的源 MAC 地址。 |
| `-b, --dmac ` | 覆盖第一批的目的 MAC 地址。 |
| `-s, --src ` | 覆盖第一批的源 IP 地址。 |
| `-d, --dst ` | 覆盖第一批的目的 IP 地址。 |
| `-p, --protocol ` | 覆盖第一批的协议。 |
| `-q, --sport ` | 覆盖第一批的源端口。 |
| `-r, --dport ` | 覆盖第一批的目的端口。 |
| `-n, --threads ` | 覆盖第一批的线程数。 |
| `-I, --interval ` | 覆盖第一批的发送间隔(微秒)。 |
| `-t, --duration ` | 覆盖第一批的持续时间。 |
| `-m, --pl ` | 覆盖第一批的 payload。 |
| `-j, --pps ` | 覆盖第一批的每秒数据包数。 |
| `-k, --bps ` | 覆盖第一批的每秒字节数。 |
| `--wait ` | 覆盖第一批的等待完成标志。[可选值: true, false] |
| `--max-pkt ` | 覆盖第一批的最大数据包计数。 |
| `--max-byt ` | 覆盖第一批的最大字节计数。 |
| `--csum ` | 覆盖第一批的校验和标志。[可选值: true, false] |
| `--l4-csum ` | 覆盖第一批的 L4 校验和标志。[可选值: true, false] |
| `--min-ttl ` | 覆盖第一批的最小 TTL。 |
| `--max-ttl ` | 覆盖第一批的最大 TTL。 |
| `--min-id ` | 覆盖第一批的最小 ID。 |
| `--max-id ` | 覆盖第一批的最大 ID。 |
| `--syn ` | 覆盖第一批的 SYN 标志。[可选值: true, false] |
| `--ack ` | 覆盖第一批的 ACK 标志。[可选值: true, false] |
| `--fin ` | 覆盖第一批的 FIN 标志。[可选值: true, false] |
| `--rst ` | 覆盖第一批的 RST 标志。[可选值: true, false] |
| `--psh ` | 覆盖第一批的 PSH 标志。[可选值: true, false] |
| `--urg ` | 覆盖第一批的 URG 标志。[可选值: true, false] |
| `--ece ` | 覆盖第一批的 ECE 标志。[可选值: true, false] |
| `--cwr ` | 覆盖第一批的 CWR 标志。[可选值: true, false] |
| `--code ` | 覆盖第一批的代码。 |
| `--type ` | 覆盖第一批的类型。 |
| `--min-len ` | 覆盖第一批的最小长度。 |
| `--max-len ` | 覆盖第一批的最大长度。 |
| `--static ` | 覆盖第一批的静态标志。[可选值: true, false] |
| `--file ` | 覆盖第一批的文件标志。[可选值: true, false] |
| `--string ` | 覆盖第一批的 payload 是否为字符串的标志。[可选值: true, false] |
## 📝 配置
配置文件是一个 JSON 文件,它定义了日志记录选项和要生成的数据包批次。每个批次都可以有自己的配置,工具将依次执行每个批次。
默认路径为 `./config.json`,但你可以使用 `-c` 或 `--cfg` 命令行参数指定不同的路径。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `logger` | Logger 对象 | 该日志对象包含与程序和文件日志记录相关的设置。 |
| `tech` | Tech 对象 | 该技术对象包含与数据包生成技术(例如 AF_XDP、DPDK 等)相关的设置。 |
| `batch` | Batch 对象 | 该批次对象包含批次列表和覆盖设置。 |
### Logger 对象
Logger 对象包含与 `stdout`/`stderr` 和磁盘日志记录相关的设置。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `level` | Log Level 枚举 (字符串) | 控制台和文件日志记录的日志级别。 |
| `path` | 字符串 | `logs/` | 日志文件或目录的路径。 |
| `path_is_file` | 布尔值 | `false` | `path` 中指定的路径是文件还是目录。如果为 `false`,将在指定目录中创建基于当前日期和时间命名的日志文件。如果为 `true`,日志将写入指定的文件。 |
| `date_format_file` | 字符串 | `"%Y-%m-%d"` | 如果 `path_is_file` 为 `false`,用于日志文件名的日期格式。这使用了与 `chrono` crate 的 `format` 方法相同的格式。 |
| `date_format_line` | 字符串 | `"%Y-%m-%d %H:%M:%S"` | 每条日志行使用的日期格式。这使用了与 `chrono` crate 的 `format` 方法相同的格式。 |
日志级别可以设置为以下值之一(不区分大小写):
* `trace`
* `debug`
* `info`
* `warn`
* `error`
* `fatal`
### Tech 对象
Tech 对象包含与数据包生成技术(例如 AF_XDP、DPDK 等)相关的设置。这允许你指定用于数据包生成的技术及任何相关的设置。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `type` | Tech Type 枚举 (字符串) | `AfXdp` | 用于数据包生成的类型。 |
| `opts` | Tech 选项 | `{}` | 一个 JSON 对象,包含特定于所选技术的选项。可用的选项取决于 `type` 字段中指定的技术类型。 |
技术类型可以设置为以下值之一(不区分大小写):
* `af_xdp`, `afxdp`, `af-xdp`
#### AF_XDP 选项
以下是 AF_XDP 的可用选项。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `if_name` | 字符串 | `None` | 用于 AF_XDP 的网络接口名称。如果源 IP 没有绑定到你正在使用的接口,你将需要显式设置此项。 |
| `queue_id` | 整数 | `None` | 如果设置,指定用于**所有** AF_XDP 套接字的固定队列 ID。 |
| `need_wakeup` | 布尔值 | `false` | 是否在 AF_XDP 套接字上设置需要唤醒标志。 |
| `shared_umem` | 布尔值 | `false` | 是否为所有 AF_XDP 套接字使用共享 UMEM。如果为 `false`,每个套接字将拥有自己的 UMEM。 |
| `batch_size` | 整数 | `32` | 使用 AF_XDP 时每批发送的数据包数量。这可以通过减少系统调用的数量来帮助提高性能。 |
| `zero_copy` | 布尔值 | `false` | 是否以零拷贝模式绑定 AF_XDP 套接字。 |
| `sock_cnt` | 整数 | `None` | 要使用的 AF_XDP 套接字数量。如果设置为 `0`,程序将使用系统上可用的 CPU 核心数。 |
### Batch 对象
Batch 对象包含批次列表和覆盖设置。每个批次定义了一组具有特定配置的要生成的数据包。工具将依次执行每个批次,从而允许复杂的数据包生成场景(不过这也是可配置的!)。
| 名称 | | 默认值 | 描述 |
| --- | --- | --- | --- |
| `batches` | Batch Data 对象列表 | `[]` | 要执行的批次列表。每个批次将按顺序执行。 |
| `ovr_opts` | Override 对象 | `None` | 一个选项对象,包含用于覆盖所有批次的通用设置。 |
#### Batch Data 对象
以下是每个批次的可用设置。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `name` | 字符串 | `None` | 在记录日志/打印信息时用于批次的可选名称。 |
| `iface` | 字符串 | `None` | 用于批次的网络接口。如果所使用的源 IP 没有绑定到你正在使用的接口,则此项是必需的。 |
| `wait_for_finish` | 布尔值 | `true` | 是否在开始下一个批次之前等待当前批次完成。如果为 `false`,程序将在发送完当前批次的所有数据包后立即启动下一个批次,而无需等待任何线程完成。 |
| `max_pkt` | 整数 | `None` | 批次要发送的最大数据包数量。如果设置,这将覆盖持续时间设置。 |
| `max_byt` | 整数 | `None` | 批次要发送的最大字节数。如果设置,这将覆盖持续时间设置。 |
| `pps` | 整数 | `None` | 批次要发送的目标每秒数据包数。这用于控制数据包的发送速率。 |
| `bps` | 整数 | `None` | 批次要发送的目标每秒字节数。这用于控制数据包的发送速率。 |
| `duration` | 整数 | `None` | 运行批次的持续时间(以秒为单位)。 |
| `send_interval` | 整数 | `1000000`(1 秒) | 在每个线程上发送数据包之间等待的间隔(以微秒为单位)。这可用于控制数据包的发送速率。`0` 将完全跳过 `sleep` 调用,这对于**最大性能**是最好的。 |
| `thread_cnt` | 整数 | `1` | 用于在批次中发送数据包的线程数。使用更多线程可以通过允许更多并发数据包发送来帮助提高性能。使用 `0` 将使用可用的 CPU 核心数。 |
| `opt_eth` | Ethernet 选项对象 | `None` | 包含以太网头部设置的可选对象。如果未设置,程序将使用以太网头部的默认值。 |
| `opt_ip` | IP 选项对象 | `None` | 包含 IP 头部设置的可选对象。如果未设置,程序将使用 IP 头部的默认值。 |
| `opt_protocol` | Protocol 选项对象 | `None` | 包含协议头部(例如 TCP、UDP、ICMP 等)设置的可选对象。如果未设置,程序将使用协议头部的默认值。 |
| `opt_payload` | Payload 选项对象 | `None` | 包含数据包 payload 设置的可选对象。如果未设置,程序将使用默认的 payload。 |
* 如果没有定义接口,程序将尝试使用定义的第一个源 IP 地址检索接口名称([来源](https://github.com/Packet-Batch/pktbatch-rs/blob/main/src/util/net.rs#L168))。
* 这意味着你**必须**定义源 IP 或接口。
##### Ethernet 选项对象
以下是以太网头部的可用设置。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `src_mac` | 字符串 | `None` | 要在以太网头部中使用的源 MAC 地址。 |
| `dst_mac` | 字符串 | `None` | 要在以太网头部中使用的目的 MAC 地址。 |
* 如果未定义源 MAC 地址,它将尝试检索正在使用的接口的 MAC 地址([来源](https://github.com/Packet-Batch/pktbatch-rs/blob/main/src/util/net.rs#L82))。
* 如果未定义目的 MAC 地址,它将尝试检索默认网关的 MAC 地址([来源](https://github.com/Packet-Batch/pktbatch-rs/blob/main/src/util/net.rs#L116))。
##### IP 选项对象
以下是 IP 头部的可用设置。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `src` | 字符串 | `None` | 支持 CIDR 范围和 DNS 解析的单个源 IP 地址。示例:`192.168.1.1/24`、`example.com`、`localhost` |
| `srcs` | 字符串列表 | `None` | 类似于 `src`,但允许指定多个源 IP 地址。程序将为每个数据包随机选择所提供的 IP 地址之一。 |
| `dst` | 字符串 | `None` | 支持 CIDR 范围和 DNS 解析的单个目的 IP 地址。示例:`192.168.1.1/24`、`example.com`、`localhost` |
| `dsts` | 字符串列表 | `None` | 类似于 `dst`,但允许指定多个目的 IP 地址。程序将为每个数据包随机选择所提供的 IP 地址之一。 |
| `tos` | 整数 | `0` | 要在 IP 头部中使用的服务类型 (TOS) 字段。 |
| `ttl_min` | 整数 | `64` | 要在 IP 头部中使用的最小生存时间 (TTL) 值。每个数据包的实际 TTL 将在 `ttl_min` 和 `ttl_max` 之间随机生成。 |
| `ttl_max` | 整数 | `64` | 要在 IP 头部中使用的最大生存时间 (TTL) 值。每个数据包的实际 TTL 将在 `ttl_min` 和 `ttl_max` 之间随机生成。 |
| `id_min` | 整数 | `None` | 要在 IP 头部中使用的最小 ID 值。每个数据包的实际 ID 将在 `id_min` 和 `id_max` 之间随机生成。 |
| `id_max` | 整数 | `None` | 要在 IP 头部中使用的最大 ID 值。每个数据包的实际 ID 将在 `id_min` 和 `id_max` 之间随机生成。 |
| `do_csum` | 布尔值 | `true` | 是否计算并设置 IP 头部校验和。如果为 `false`,校验和将被设置为 `0`(适用于硬件卸载) |
* 如果没有定义源 IP 地址,程序将尝试检索正在使用的接口的 IP 地址([来源](https://github.com/Packet-Batch/pktbatch-rs/blob/main/src/util/net.rs#L191))。
##### Protocol 选项对象
Protocol 选项对象包含协议头部(例如 TCP、UDP、ICMP 等)的设置。可用的设置取决于为批次指定的协议。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `type` | 字符串 | `tcp` | 用于批次的协议类型。支持的值包括 `tcp`、`udp` 和 icmp。 |
| `opts` | 特定协议的选项对象 | `{}` | 一个 JSON 对象,包含特定于所选协议类型的选项。可用的选项取决于 `type` 字段中指定的协议类型。 |
###### TCP 选项
以下是 TCP 协议的可用选项。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `src_port` | 整数 | `None` | 要在 TCP 头部中使用的源端口。`0` 或 `None` 在 `1` 和 `65535` 之间随机生成端口。 |
| `dst_port` | 整数 | `None` | 要在 TCP 头部中使用的目的端口。`0` 或 `None` 在 `1` 和 `65535` 之间随机生成端口。 |
| `flag_syn` | 布尔值 | `false` | 是否在 TCP 头部中设置 SYN 标志。 |
| `flag_ack` | 布尔值 | `false` | 是否在 TCP 头部中设置 ACK 标志。 |
| `flag_fin` | 布尔值 | `false` | 是否在 TCP 头部中设置 FIN 标志。 |
| `flag_rst` | 布尔值 | `false` | 是否在 TCP 头部中设置 RST 标志。 |
| `flag_psh` | 布尔值 | `false` | 是否在 TCP 头部中设置 PSH 标志。 |
| `flag_urg` | 布尔值 | `false` | 是否在 TCP 头部中设置 URG 标志。 |
| `flag_ece` | 布尔值 | `false` | 是否在 TCP 头部中设置 ECE 标志。 |
| `flag_cwr` | 布尔值 | `false` | | 是否在 TCP 头部中设置 CWR 标志。 |
| `do_csum` | 布尔值 | `true` | 是否计算并设置 TCP 头部校验和。如果为 `false`,校验和将被设置为 `0`(适用于硬件卸载) |
###### UDP 选项
以下是 UDP 协议的可用选项。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `src_port` | 整数 | `None` | 要在 UDP 头部中使用的源端口。`0` 或 `None` 在 `1` 和 `65535` 之间随机生成端口。 |
| `dst_port` | 整数 | `None` | 要在 UDP 头部中使用的目的端口。`0` 或 `None` 在 `1` 和 `65535` 之间随机生成端口。 |
| `do_csum` | 布尔值 | `true` | 是否计算并设置 UDP 头部校验和。如果为 `false`,校验和将被设置为 `0`(适用于硬件卸载) |
###### ICMP 选项
以下是 ICMP 协议的可用选项。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `icmp_type` | 整数 | `8`(回显请求) | 要在 ICMP 头部中使用的 ICMP 类型。 |
| `icmp_code` | 整数 | `0` | 要在 ICMP 头部中使用的 ICMP 代码。 |
| `do_csum` | 布尔值 | `true` | 是否计算并设置 ICMP 头部校验和。如果为 `false`,校验和将被设置为 `0`(适用于硬件卸载) |
#### Payload 选项对象
以下是数据包 payload 的可用设置。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `len_min` | 整数 | `None` | payload 的最小长度(以字节为单位)。每个数据包的实际 payload 长度将在 `len_min` 和 `len_max` 之间随机生成。 |
| `len_max` | 整数 | `None` | payload 的最大长度(以字节为单位)。每个数据包的实际 payload 长度将在 `len_min` 和 `len_max` 之间随机生成。 |
| `is_static` | 布尔值 | `false` | 是否对批次中的所有数据包使用静态 payload。如果为 `false`,将根据指定的长度为每个数据包生成随机 payload。 |
| `is_file` | 布尔值 | `false` | 是否从文件读取 `exact` payload。如果为 `true`,`len_min` 和 `len_max` 字段将被忽略,并且将从 `file_path` 字段中指定的文件读取 payload。 |
| `is_string` | 布尔值 | `false` | `exact` payload 是否为字符串。如果为 `true`,payload 将被视为 UTF-8 字符串。如果为 `false`,payload 将被视为原始字节。 |
| `exact` | 字符串 | `None` | 用于批次中数据包的确切 payload。此字段的解释取决于 `is_file` 和 `is_string` 的值。如果 `is_file` 为 `true`,则此字段被视为从中读取 payload 的文件路径。如果 `is_string` 为 `true`,则此字段被视为用作 payload 的 UTF-8 字符串。如果 `is_file` 和 `is_string` 都为 `false`,则此字段被视为表示 payload 原始字节的十六进制字符串,以空格分隔(例如 `FF FF FF 04`)。 |
#### Override 选项
以下是可以为所有批次设置的可用覆盖选项。
| 名称 | 类型 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `iface` | 字符串 | `None` | 覆盖所有批次的网络接口。 |
## ⚠️ 免责声明
本项目仅用于教育和测试目的。作者不对本工具的任何误用负责。在任何网络或系统上使用本工具之前,请务必确保你拥有适当的授权。
## ✍️ 致谢
* [Christian Deacon](https://github.com/gamemann)
标签:AF_PACKET, AF_XDP, C, DNS枚举, DNS解析, DPDK, Linux网络, Rust, 内核驱动, 可视化界面, 安全渗透, 实时处理, 开源项目, 性能基准测试, 数据包生成, 网络协议, 网络安全, 网络安全工具, 网络流量审计, 网络流量生成, 网络测试工具, 自定义Payload, 负载测试, 通知系统, 隐私保护, 零拷贝网络, 高并发