qre-tool 参考¶
qre-tool 是 QRE 唯一的用户态操作入口。它负责 profile 生命周期、daemon 模式、配置规范化、内核状态查看、session 安装、CID 控制、eBPF 共享端口调试和 capture 生成。
全局选项¶
| 选项 | 适用命令 | 说明 |
|---|---|---|
--json |
show、show-cid-map |
输出 JSON。其他命令会解析该选项,但通常没有 JSON 输出路径。 |
--dry-run |
up、reload、down、daemon、help |
打印操作计划,不执行内核、网络设备或 daemon runtime 修改。 |
--help、-h |
help、daemon |
打印帮助。daemon --help 会显示 daemon 专属选项。 |
全局选项会先从参数列表中过滤,因此通常可放在命令前后。为了可读性,建议放在命令前:
常用命令总览¶
| 命令 | 是否通常需要 root | 说明 |
|---|---|---|
help |
否 | 打印帮助。 |
show [device] |
否 | 查看所有设备或指定设备的内核状态。 |
refresh <device> |
否 | 刷新并显示指定设备的 Dest profile 诊断。 |
showconf <config> |
否 | 解析全局配置或接口 profile,输出标准化 JSON。 |
strip <profile> |
否 | 读取配置目录中的 profile 并输出标准化 JSON。 |
up <profile> |
是 | 一次性准备 profile。 |
reload <profile> |
是 | 重新同步 profile。 |
down <profile> |
是 | 清理 profile。 |
daemon <profile> |
是 | 运行持久 server/client 控制面。 |
syncconf <device> <config> |
是 | 把接口配置同步到内核。 |
delete <device> |
是 | 删除内核中的 QRE 设备状态。 |
set <device> role ... |
是 | 从命令行构造最小 server/client 配置并同步。 |
install-session、update-session |
是 | 安装或更新内核 session。 |
adopt-cid、release-cid |
是 | 管理内核 CID 分流键。 |
create-*map、register-* |
是 | BPF map 和共享 socket 调试控制。 |
session-plan、session-capture |
否 | 用户态握手计划和 pcap 生成。 |
session-demo、shared-port-* |
多数需要 root | 集成、验收或调试命令。 |
生命周期命令¶
strip¶
读取 ${QRE_CONFIG_DIR:-/etc/qre/dev}/<profile>.conf,同时读取全局配置用于状态目录解析,然后输出 profile 的标准化 JSON。profile 名只能包含 ASCII 字母、数字、-、_,不能以 . 开头,不能包含 / 或 \。
up¶
执行一次性准备:
- 校验 profile。
- 加载
qre.ko,除非QRE_MODULE_LOAD=false。 - 执行
PreUphooks。 - 通过 netlink 同步配置。
- 设置 link up。
- 替换设备地址。
- 执行
PostUphooks。 - 在 state dir 保存 profile state。
失败时会尝试删除已配置地址、删除内核设备状态并移除 profile state。
reload¶
重新读取 profile,同步内核配置并替换地址。如果保存的旧地址和新地址不同,会先删除旧地址。reload 不负责长期 daemon 的重连策略;systemd 场景通常使用:
down¶
执行清理:
- 执行
PreDownhooks。 - 删除保存的或当前配置中的设备地址。
- 删除内核设备状态。
- 执行
PostDownhooks。 - 移除 profile state。
daemon¶
daemon 先执行与 up 相同的准备,然后按 profile 角色运行持久控制面:
- server:持有监听/fallback UDP socket、共享端口 eBPF loader 生命周期、外部 REALITY/QUIC 握手、session 安装、CID adoption 和退出清理。
- client:运行重连循环,握手成功后安装 session,写 ready file;会话丢失后用有界指数退避重试。
daemon 选项:
| 选项 | 值 | 说明 |
|---|---|---|
--config-dir <path> |
路径 | 覆盖 profile 目录,同时设置 QRE_CONFIG_DIR。 |
--global-config <path> |
路径 | 覆盖全局配置路径,同时设置 QRE_GLOBAL_CONFIG。 |
--state-dir <path> |
路径 | 覆盖状态目录,同时设置 QRE_STATE_DIR。 |
--bpf-elf <path> |
路径 | 覆盖 BPF ELF,同时设置 QRE_BPF_ELF。 |
--pin-dir <path> |
路径 | 覆盖 BPF pin 目录,同时设置 QRE_BPF_PIN_DIR。 |
--server-underlay <ip:port> |
socket addr | 测试/调试时覆盖服务端 underlay。 |
--client-underlay <ip:port> |
socket addr | 测试/调试时覆盖客户端 underlay。 |
--run-for-ms <ms> |
非零 u64 | 运行指定毫秒后退出,主要用于测试。 |
状态和配置命令¶
show¶
显示设备角色、计数器、Dest profile、session、CID adoption、BPF map 同步、共享 socket 和共享 loader 状态。具体字段取决于当前 qre.ko ABI。
refresh¶
刷新指定设备的 Dest profile,并打印探测结果。常用于确认 Dest 是否可达、cache 是否新鲜。
showconf¶
解析全局配置或接口 profile,并输出稳定 JSON。适合在 CI 或部署脚本中作为配置校验。
syncconf¶
读取接口配置并同步到内核。命令参数中的 <device> 必须与配置里的 Device 一致。
delete¶
删除内核中的 QRE 设备状态。完整 profile 清理更推荐使用 qre-tool down <profile>,因为它还会处理地址、hooks 和 state。
set¶
sudo qre-tool set <device> role server \
Address=<cidr> Listen=<ip:port> MTU=<mtu> Dest=<host:port> ServerName=<sni>
sudo qre-tool set <device> role client \
Address=<cidr> Endpoint=<host:port> MTU=<mtu> ServerName=<sni> \
[PersistentKeepalive=<seconds>]
set 是低层调试命令。它会构造一个最小配置并同步到内核,REALITY key 和 short id 使用占位值:
- server 占位:
RealityPrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=,RealityShortIds = 00 - client 占位:
RealityPublicKey = AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE=,RealityShortId = 00
生产配置应使用 profile 文件和 daemon/up。
set 字段别名:
| 标准字段 | 接受的别名 |
|---|---|
Address |
address |
Listen |
listen |
Endpoint |
endpoint |
MTU |
mtu |
Dest |
dest |
ServerName |
server-name、server_name、sni |
PersistentKeepalive |
persistent-keepalive、persistent_keepalive |
Session 命令¶
install-session 和 update-session¶
sudo qre-tool install-session <device> \
SessionId=<64hex> ConnectionId=<hex> \
TxKey=<32hex> RxKey=<32hex> \
TxHpKey=<32hex> RxHpKey=<32hex> \
TxIv=<24hex> RxIv=<24hex> \
KeyEpoch=<u64> PacketNumber=<u64> \
[NextRxKey=<32hex> NextRxHpKey=<32hex> NextRxIv=<24hex>] \
[UnderlayLocalIPv4=<ip> UnderlayLocalPort=<port> UnderlayPeerIPv4=<ip> UnderlayPeerPort=<port>]
sudo qre-tool update-session <device> ...
两者使用同一组字段。成功后都会自动采用该 session 的 ConnectionId。
| 字段 | 必填 | 格式 | 说明 |
|---|---|---|---|
SessionId |
是 | 64 个 hex 字符 | 32 字节 session id。 |
ConnectionId |
是 | 偶数长度 hex | QRE routed connection id。 |
TxKey、RxKey |
是 | 32 个 hex 字符 | QUIC packet protection key。 |
TxHpKey、RxHpKey |
是 | 32 个 hex 字符 | QUIC header protection key。 |
TxIv、RxIv |
是 | 24 个 hex 字符 | QUIC IV。 |
KeyEpoch |
是 | u64 | key epoch。 |
PacketNumber |
是 | u64 | 当前 packet number。 |
NextRxKey、NextRxHpKey、NextRxIv |
否 | 同对应当前字段 | rekey 接收侧下一组 key。 |
UnderlayLocalIPv4 |
条件必填 | IPv4 | underlay 本地 IP。 |
UnderlayLocalPort |
条件必填 | 非零端口 | underlay 本地端口。 |
UnderlayPeerIPv4 |
条件必填 | IPv4 | underlay 对端 IP。 |
UnderlayPeerPort |
条件必填 | 非零端口 | underlay 对端端口。 |
只要出现任意 underlay 字段,四个 underlay 字段都必须出现。
字段支持 kebab-case 和 snake_case 别名,例如 session-id、session_id、tx-hp-key、tx_hp_key。
adopt-cid 和 release-cid¶
显式管理内核 CID 控制表。主要用于 rekey、迁移和 demux 控制测试。生产握手路径通常由 session 安装自动完成。
BPF map 和共享 socket 命令¶
create-cid-map¶
创建并 pin 一个 QRE_CID_ROUTES BPF hash map。map 形状:
- key size:21 字节,包含 CID 长度和最多 20 字节 CID。
- value size:
u32。 - max entries:4096。
create-reuseport-socket-map¶
创建并 pin 一个 QRE_SOCKETS BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,包含两个 slot:
- index 0:userspace/fallback socket。
- index 1:kernel socket。
实际填充 socket 由 shared-port-loader 完成。
register-cid-map 和 unregister-cid-map¶
sudo qre-tool register-cid-map BpfMapPath=/sys/fs/bpf/qre-cid-routes
sudo qre-tool register-cid-map BpfMapFd=<fd>
sudo qre-tool unregister-cid-map
注册后,内核会把已采用和未来采用的 CID 镜像到该 map。BpfMapFd=<fd> 只对当前进程中的有效 fd 有意义;跨进程调试通常使用 BpfMapPath=<path>。
show-cid-map¶
qre-tool show-cid-map BpfMapPath=/sys/fs/bpf/qre-cid-routes
qre-tool --json show-cid-map BpfMapPath=/sys/fs/bpf/qre-cid-routes
读取 pinned QRE_CID_ROUTES map。文本输出列出 entry 数量以及每个 connection_id 和 socket_index。
register-shared-socket 和 unregister-shared-socket¶
向 qre.ko 注册共享端口 kernel-slot UDP socket。内核会验证 fd 是调用者 network namespace 中的 IPv4 UDP datagram socket。fd 不能来自无关进程。
共享端口调试命令¶
这些命令主要用于验收、开发和定位 eBPF 分流问题。生产 server runtime 由 qre-tool daemon <server-profile> 持有。
shared-port-loader¶
sudo qre-tool shared-port-loader \
BpfElf=<path> Listen=<ip:port> \
UserspaceSocketFd=<fd>
sudo qre-tool shared-port-loader \
BpfElf=<path> Listen=<ip:port> \
UserspaceBind=true \
[PinDir=<bpffs-dir>] [RegisterCidMap=true|false] \
[RoutedCidLen=17..20] [Device=<device>] \
[ReadyFile=<path>] [RunForMs=<ms>]
作用:加载 BPF ELF,设置 routed CID 长度,绑定或接收 userspace socket,创建 kernel socket,填充 socket map,pin BPF map,注册 CID map 和 shared socket,attach qre_reuseport_demux,直到收到信号或 RunForMs 到期后清理。
shared-port-loader-check¶
sudo qre-tool shared-port-loader-check \
BpfElf=<path> Listen=<ip:port> ConnectionId=<hex> \
[PinDir=<bpffs-dir>] [RegisterCidMap=true|false] \
[RoutedCidLen=17..20] [Device=<device>]
短生命周期验收命令。它会建立 userspace/kernel SO_REUSEPORT socket 组,填充 QRE_SOCKETS 和 QRE_CID_ROUTES,attach 程序,验证 fallback、kernel slot 和 detach 后行为。若提供 Device,还会检查 qre-tool show Device 中的共享端口计数。
shared-port-session-demo¶
sudo qre-tool shared-port-session-demo \
<server-config> <client-config> BpfElf=<path> \
[PinDir=<bpffs-dir>] [RegisterCidMap=true|false] \
[RoutedCidLen=17..20] [ReadyFile=<path>] [RunForMs=<ms>] \
[ServerUnderlay=<ip:port>] [ClientUnderlay=<ip:port>]
在真实 UDP socket 上跑一轮 REALITY/QUIC 握手,并证明 loader 已注册 map/socket 后再安装 session。
shared-port-handshake-daemon¶
sudo qre-tool shared-port-handshake-daemon \
<server-config>... BpfElf=<path> \
[PinDir=<bpffs-dir>] [RegisterCidMap=true|false] \
[RoutedCidLen=17..20] [ReadyFile=<path>] [RunForMs=<ms>]
加载一个或多个 server config 作为共享 front。所有 config 必须共享 Listen、ServerName、Dest、RealityPrivateKey 和 RealityMaxTimeDiff,且同一 ServerName 下 short id 不能重叠。每个认证成功的握手按 short id 选择目标 device。
shared-port-handshake-client¶
qre-tool shared-port-handshake-client \
<client-config> \
[ServerUnderlay=<ip:port>] [ClientUnderlay=<ip:port>] \
[InstallSession=true|false]
执行一次真实 UDP REALITY/QUIC client 握手。InstallSession=true 时还会把客户端 session 安装到 qre.ko 并采用 routed CID,因此需要 root。
共享端口字段说明:
| 字段 | 适用命令 | 默认值 | 说明 |
|---|---|---|---|
BpfElf |
所有 shared-port-* loader/daemon/demo |
无,必填 | release BPF ELF 路径。 |
Listen |
shared-port-loader、shared-port-loader-check |
无,必填 | 数字 ip:port。 |
ConnectionId |
shared-port-loader-check |
无,必填 | hex,长度必须等于 RoutedCidLen。 |
UserspaceSocketFd |
shared-port-loader |
二选一 | 已绑定 userspace socket fd。 |
UserspaceBind |
shared-port-loader |
二选一 | 必须为 true,由命令自己绑定 userspace socket。 |
PinDir |
多数共享端口命令 | /sys/fs/bpf |
bpffs pin 目录。 |
RegisterCidMap |
多数共享端口命令 | true |
是否向 qre.ko 注册 CID map。 |
RoutedCidLen |
多数共享端口命令 | 默认 routed CID 长度 | 允许 17..20。 |
Device |
loader/check | 无 | 用于 qre-tool show 观察共享端口计数。 |
ReadyFile |
loader/daemon/demo | 无 | loader 就绪后写入的文件。 |
RunForMs |
loader/daemon/demo | 无 | 非零毫秒数,到期退出。 |
ServerUnderlay |
demo/client/session 命令 | server config 的 Listen |
覆盖服务端 underlay 地址。 |
ClientUnderlay |
demo/client/session 命令 | 测试默认地址 | 覆盖客户端本地 underlay 地址。 |
InstallSession |
shared-port-handshake-client |
false |
是否把握手结果安装到内核。 |
字段通常也接受 kebab-case 和 snake_case,例如 bpf-elf、bpf_elf、run-for-ms、run_for_ms。
用户态 session 和 capture 命令¶
session-plan¶
qre-tool session-plan <server-config> <client-config> \
[ServerUnderlay=<ip:port> ClientUnderlay=<ip:port>]
在内存中跑 REALITY/QUIC CONNECT-IP 握手,输出 server/client 的 install-session 参数,不触碰 netlink。适合 namespace 测试或人工检查派生结果。
session-demo¶
sudo qre-tool session-demo <server-config> <client-config> \
[ServerUnderlay=<ip:port> ClientUnderlay=<ip:port>]
在内存中跑握手,并把 server/client 两端 session 都安装到内核。它是验证命令,不是生产生命周期入口。
session-capture¶
qre-tool session-capture \
<valid-client|invalid-short-id|wrong-sni|malformed-initial|random-udp> \
<server-config> <client-config> <pcap> \
[ServerUnderlay=<ip:port> ClientUnderlay=<ip:port>]
生成原始 IPv4 UDP pcap,不触碰 netlink,也不加载 qre.ko。
| 场景 | 说明 |
|---|---|
valid-client、valid |
有效客户端,应完成握手。 |
invalid-short-id |
short id 错误,应被拒绝。 |
wrong-sni |
SNI 错误,应被拒绝。 |
malformed-initial |
伪造 malformed QUIC Initial。 |
random-udp |
随机 UDP payload。 |
命令会在有效客户端被拒绝或无效客户端被接受时失败。
退出码¶
成功返回 0。配置校验、参数错误、权限不足、netlink 错误、BPF 错误或握手断言失败时返回非零,CLI 主入口通常使用退出码 2。