btdt1983/chameleon-pq
GitHub: btdt1983/chameleon-pq
用 Rust 编写的实验性混合后量子 VPN,结合 ML-KEM-768/X25519 密钥协商与 ML-DSA-65/Ed25519 认证,并集成数据包混淆与流量整形功能,用于学习和参考而非生产环境。
Stars: 0 | Forks: 0
# Chameleon-PQ
[](https://github.com/btdt1983/chameleon-pq/actions/workflows/ci.yml)
[](https://crates.io/crates/chameleon-pq)
[](https://github.com/btdt1983/chameleon-pq/releases)
[](LICENSE)
*🇬🇧 English | [🇩🇪 Deutsch](README.de.md)*
使用 Rust 编写的实验性混合后量子 VPN。结合了 ML-KEM-768 (KEM)
与 X25519 进行密钥协商,并使用混合的 Ed25519 + ML-DSA-65 (FIPS 204)
签名进行对端认证,基于 UDP 运行,并在
Linux/macOS/Windows 上提供 TUN 接口。
## 为什么需要后量子?
当今使用的几乎所有加密技术——网站上的挂锁图标、VPN、消息
应用——都依赖于足够规模的**量子计算机**能够破解的数学难题(RSA、
椭圆曲线)。这些机器虽然还不存在,但正在建造中。
问题在于**“现在窃取,将来解密”**:攻击者可以*今天*记录你的
加密流量,将其存储起来,然后静静等待——等未来有了量子计算机,
再将其解密。因此,任何需要长期保密的内容,在量子计算机真正到来之前,
就已经面临风险了。
Chameleon-PQ 正是为那个时代构建的。它采用了**混合**设计,将
当今经过验证的加密技术 (X25519) 与一种全新的**抗量子**算法
(ML-KEM-768,由 NIST 标准化) 结合在一起。只要*两者中有任何一个*
保持安全,你的流量就能受到保护——这样,在不放弃我们今天已经信任的安全性的同时,
你获得了防范未来量子计算机的防御能力。
## ⚠️ 安全状态:实验性——风险自负
Chameleon-PQ 是**实验性**的,尚未经过**官方的、
独立的安全审计**。任何自行构建的加密协议在获得资质人员审查之前都应
谨慎对待,因此**使用风险由您自行承担**。它是一个很好的学习项目、架构参考,
或者是构建正式审计系统的起点——只是目前还不能直接作为生产环境的
VPN 替代品。
已知的范围限制:
- 尚未进行外部的安全审计——对于任何自行构建的加密协议来说,这仍然是
最重要的注意事项
- **数据通道**、**握手信封**,以及现在的**数据包时间**都
被混淆了——每个数据报看起来都像是均匀的随机字节,并且可选的
流量整形(`[traffic]`,**默认关闭**;通过配置文件启用——
**Adaptive** 在使用时进行速率调整,**CBR** 用于完全恒定速率)按固定
计划发送,并使用掩护数据包填充
空闲时段,因此突发流量和空闲与活跃状态之间的差别消融在稳定的
数据流中。残余风险(有文档说明,但并未声称具有*完全*抵抗能力):隧道的
存在和总持续时间是固定站点到站点链路固有的特征,**初始**
握手突发流量处于预步调调节(pre-pacer)阶段,且默认情况下握手混淆密钥是
由公钥派生的(设置 `[obfuscation].psk_hex` 可以弥补这一点)。整形有确实的
带宽/延迟代价——配置的速率既是下限(在 CBR 模式下),也是吞吐量的上限
- ML-DSA 已集成用于身份验证,但密钥交换仍然将
ML-KEM-768 与 X25519 配对使用(没有第二个 PQ KEM)
## 已实现功能
- 混合后量子握手 (ML-KEM-768 + X25519,均为临时生成 → PFS)
- 相互认证:3 条消息(2-RTT)握手,双方对端均签署
记录;响应方在发起方的 Confirm 验证通过之前不会给予信任
- 返回路由可达性 Cookie (WireGuard 风格,无状态):响应方在
发起方回显与其源地址绑定的 Cookie 之前,不进行
昂贵的 ML-KEM/DH/ML-DSA 计算,因此伪造/未经证实的源无法触发昂贵的
握手或大规模反射响应。CookieChallenge 是一个全尺寸的
混淆消息,因此它会与握手的其余部分融为一体
- 混合 Ed25519 + ML-DSA-65 (FIPS 204) 记录签名用于对端
认证(预共享身份)——只要*任一*方案未被破解,签名就有效;当未配置 ML-DSA
密钥时,回退为仅使用 Ed25519
- 可插拔的数据通道 AEAD:ChaCha20-Poly1305(通过 `ring` 实现,常数时间,
通用默认选项)和 AEGIS-256X2(CAESAR 获胜者,在带有 AES 硬件加速的 CPU 上更快),
通过硬件感知协商进行选择,并将该选择绑定到记录中以防止降级攻击
- 混淆数据通道(QUIC 风格的头部保护):每个数据
数据报看起来都像是均匀的随机字节——没有静态的类型字节,没有可见的 session_id,
没有可见的单调计数器。头部使用从 AEAD 标签样本中提取的密钥流
(通过 HMAC-SHA256)进行掩码处理,并且真实的帧类型
携带在*加密的载荷内部*,因此保活(keepalive)数据包与
真实数据无法区分。可配置的长度填充(关闭 / 分桶 / 完全)隐藏了数据包的
大小。头部完整性仍然来自 AEAD(恢复出的头部作为
关联数据),与之前完全一样——掩码仅用于提供机密性
- 混淆握手信封(静态密钥,`hsobf.rs`):握手消息
被包裹在一层由预共享身份(或可选的 `psk_hex`)生成密钥的 ChaCha20-Poly1305 中,
并被拆分为大小经过抖动处理的带有掩码头部的片段——握手突发流量不再显示恒定的类型字节或
固定的片段结构。真正的握手加密逻辑没有改变;这是一个
纯粹的外部混淆层(该混淆层没有前向安全性)
- 时间 / 掩护流量整形(`pacer.rs`,`[traffic]`,可选,**默认
关闭**):数据包按固定的时间表发出,空闲的槽位会被
接收方静默丢弃的掩护(虚拟)数据包填满,从而隐藏了突发和
空闲与活跃状态的模式。掩护数据包是普通的带有加密的 `Padding` 内部类型的
混淆数据报,在 `Full` 填充模式下大小恒定,因此它们在网络传输上与真实数据
无法区分。Adaptive 在活动 + 冷却阶段调整速率,并在空闲时停止发送
(闲置时不消耗带宽);**CBR**
以恒定成本持续流式传输,以实现最强的隐藏效果。没有网络/协议层面的
改变——早于此功能引入的对端会安全地丢弃掩护数据包
- 每个方向的密钥独立;2048 条目的滑动窗口重放保护
- 带有防风暴机制的密钥更新,在丢包时重试,当前+上一个会话
重叠,确保传输中的流量能在切换中存活
- 片段重组,具有抗 DoS 的过期残留数据清理机制
- 保活 / 死亡对端检测
- 跨平台 TUN:Linux、macOS、Windows (Wintun)
- **终止开关**(客户端,全隧道,可选 `tun.kill_switch`):连接时安装的故障关闭
防火墙,因此如果隧道断开,不会有任何内容以明文形式泄漏到
物理网卡——只有环回、局域网、DHCP 和隧道自身的
路径保持打开。与基于 RAII 的全套路由不同,它*能在*
意外断开时存活(这正是它的意义所在),仅在主动断开连接或通过
`chameleon-pq killswitch off` 逃生舱时才会关闭。在 Linux 上使用 nftables,在 Windows 上使用 Windows 防火墙
(默认阻止出站 + 按路径放行)
- **桌面 GUI 客户端**(`chameleon-gui`,纯 Rust [iced]):一个深色主题的
Windows 应用程序——选择配置文件、连接 / 断开连接、实时状态、友好的
流量配置选择器以及应用内日志,且没有后台控制台窗口(详见下文的
[桌面客户端](#desktop-client-gui))
- 性能(无网络协议改变):数据通道 AEAD 在启动时通过快速基准测试自动选择
(在速度最快的地方使用 AEGIS-256X2,在 AEGIS 会回退到缓慢的软件 AES 时使用 ChaCha20);UDP I/O 在接收时使用 GRO,在发送时
使用可选的 GSO(`[engine].gso`,**默认关闭**——在某些路径下它会使得
下载速度暴跌,例如 Hyper-V vSwitch;通过 `quinn-udp` 实现,在旧内核 / 非 Linux 系统上按数据包进行
回退)——微基准测试将发送速率从
~0.18 Mpps 提升到了 ~9.6 Mpps;并且 seal/open 操作在所有核心上并行运行
(rayon,`[engine].workers`),在 12 线程的机器上测得的提升比例约为 ~4.5× (seal) / ~13× (open)。注意:并行处理路径对
**快速模式**(默认的 `profile = "off"`)有帮助;在开启时间整形(可选)的情况下,配置的速率会限制吞吐量,
因此速度与时间混淆是你在两者之间做出的对立权衡
- 88 个测试涵盖了握手(包括相互认证 + 分片)、混合
ML-DSA 认证(以及在 Ed25519 匹配时错误的 PQ 密钥会导致失败)、
AEAD 协商和 AEGIS 会话、关联数据头部绑定、数据
通道、重放(包括大范围重排)、MITM(双向)、密钥更新、
修剪行为、混淆数据通道(在两种密码上进行往返测试、
篡改拒绝、跨当前+上一个会话的尝试解复用、长度
填充、空的保活数据包、明文握手穿透)、以及
混淆握手信封(对称密钥派生、带抖动的先封装后分片的往返测试、
完整的相互握手、错误密钥/噪声拒绝、
重组器上限 + 修剪,以及不接受 0.1.x 的明文帧)、
时间/掩护流量(纯 pacer 调度器的 CBR/Adaptive/冷却逻辑、
掩护数据包作为 `Padding` 往返测试、以及在 `Full` 填充模式下掩护和数据包
等长 + 头部可区分)、并行加密
(并行封装的数据包均使用唯一的计数器解密,且
`decrypt_batch_par` 能区分数据和噪声)、角色分离的握手
签名(即使在使用共享身份密钥的情况下,反射的响应方签名也会作为 Confirm 被拒绝)、
有界 UDP 握手(通过真实套接字相互完成 + 在无响应方应答时干净地超时)、
身份绑定(对称、依赖对端)、低阶/全零 X25519 拒绝、以及
返回路由可达性 cookie(确定性 + 输入依赖性,以及
无 cookie 的 Init 会收到 CookieChallenge 作为响应,而不是昂贵的 Response),
以及终止开关防火墙规则集(一个默认丢弃策略,仅允许
环回、隧道传输、TUN、LAN 和 DHCP,当子网未知时省略 LAN 规则,
并拒绝不安全的接口名称)
- 针对面向攻击者的解析器(帧 + 握手解码,数据通道
和握手混淆解析器,重组器,以及入站
解密路径)的模糊测试:一个稳定的随机 + 边缘情况测试框架随 `cargo test`
(`tests/fuzz_parsers.rs`)运行,加上 `fuzz/` 目录下有覆盖率引导的 `cargo-fuzz` 目标
(nightly;每周的 CI 任务)。在各个目标上的约 1800 万次执行中未发现 panic
- 端到端隧道测试(`tests/e2e_tunnel.rs`):**真实**的隧道循环
(`tunnel_loops::run_tunnel_loops`)在双方通过环回 UDP 和 mock TUN 运行,
并且明文通过完整的握手(包括 L-4 cookie 往返)双向流动
→ seal → GSO 发送 → GRO 接收 → 解密 → TUN 路径
## 下载
每个[发布版本](../../releases/latest)中都附带了预编译的二进制文件:
- **Windows** — `chameleon-pq-
-windows-x64.zip`:一个包含桌面 GUI (`chameleon-gui.exe`)、CLI (`chameleon-pq.exe`)、
由微软签名的 `wintun.dll`、示例配置和安装说明的独立整合包。解压并运行——
无需安装其他任何东西。
- **Linux** — `chameleon-pq-linux-x8664` (CLI)。
- **crates.io** — `cargo install chameleon-pq` (CLI)。
## 桌面客户端 (GUI)
比起使用命令行,更喜欢点击连接?Windows 版本发布包含了一个原生的
桌面客户端,**chameleon-gui**,使用纯 Rust 和 [iced] 构建:
- 深色主题,带有变色龙 Logo 和匹配的任务栏图标;
- 选择你的 `config.toml`,连接 / 断开连接,并查看实时状态;
- 友好的流量配置选择器(最高隐私 · 均衡 · 高速 · 最快)和应用内日志——
后台没有控制台窗口;
- 头部有直接指向此代码库的链接。
它已包含在上面的独立 Windows 整合包中,也可以在 Linux/macOS 上通过 `cargo build --release --manifest-path gui/Cargo.toml` 从源码构建。
## 构建
需要最新的 Rust 工具链(1.80+;通过
[rustup](https://rustup.rs/) 安装)。
```
cargo build --release
cargo test
```
或者从 crates.io 安装:
```
cargo install chameleon-pq
```
## 快速开始
```
# 1. 在两个节点上生成 keypairs
./target/release/chameleon-pq keygen
# 2. 将 config.example.toml 复制为 config.toml,填入你的 seed 和
# peer 的 public key(通过带外方式交换这些信息)
# 3. 验证
./target/release/chameleon-pq --config config.toml check
# 4. 作为服务器运行(在 Linux 上使用 TUN 需要 CAP_NET_ADMIN)
sudo ./target/release/chameleon-pq --config config.toml server
# 5. 作为客户端运行
sudo ./target/release/chameleon-pq --config config.toml client \
--server 1.2.3.4:51820
```
在 Windows 上,你还需要将来自 的 `wintun.dll` 放在
二进制文件所在的目录下。
## 架构
- `crypto.rs` — 定义了带有 `Ed25519Auth`(通过 `ring`)和
`MlDsaAuth`(通过 `pqcrypto-mldsa` 实现的 ML-DSA-65)的 `Authenticator` trait,并由 `HybridAuth`
组合(所有阶段必须通过验证);以及记录哈希、HKDF
- `aead.rs` — 可插拔的数据通道 AEAD:在统一的 trait 之后实现了 `ChaCha20-Poly1305` 和
`AEGIS-256X2`(支持关联数据);启动时的
微基准测试会为机器自动选择更快的密码,并且
该选择是防降级安全的(绑定在握手记录中)
- `session.rs` — 每个方向的 AEAD 密钥、nonce 管理、通过 AAD 进行头部绑定、
滑动窗口重放、带有密钥更新的 `SessionManager`
- `tunnel.rs` — 8192 字节握手(单一 KEM 槽位,噪声填充;专门为
混合 PQ 签名进行尺寸设计)、分片/重组、带有
记录签名的有限状态机
- `frame.rs` — MTU 安全、无魔术字(magic-free)的帧(<1280 B),用于握手
信封和遗留(关闭混淆)的数据通道
- `obf.rs` — 数据通道混淆:QUIC 风格的头部保护(13 字节的
头部使用从 AEAD 标签样本派生的密钥流进行掩码处理)、内部
类型成帧(真实的帧类型在载荷内部加密)、以及可配置的长度填充
- `hsobf.rs` — 握手信封混淆:静态密钥(从
预共享的 Ed25519 公钥或可选的 PSK 派生)将整个握手
消息封装在 ChaCha20-Poly1305 中,并将其拆分为大小经过抖动处理的带有掩码
头部的片段(`derive_hs_obf_key` / `seal_and_fragment` / `unmask_fragment`
/ `open`)
- `pacer.rs` — 用于时间/掩护流量整形的纯(无 tokio)恒定速率调度器:`Pacer::next_emit` 决定每个槽位是发送真实数据包、
掩护数据包,还是什么都不发送(`ShapeMode` CBR/Adaptive);由
`main.rs` 中的异步循环驱动
- `engine.rs` — CPU 加密引擎:批量 seal/open,通过 rayon **在所有核心上并行**
运行(`encrypt_batch_par` / `decrypt_batch_par`,通过 `spawn_blocking` 从异步循环中进行桥接);常数时间、低延迟,没有 GPU
处理路径(原因详见 DESIGN.md §11–§12)
- `net.rs` — UDP 握手连线(发起方/响应方、分片、L-4
cookie)+ 返回路由可达性 `CookieState`
- `tunnel_loops.rs` — 实时隧道循环(出站 / 入站 + 握手密钥更新
多路分解 / 保活),作为可重用的 `run_tunnel_loops`,加上 `TunnelParams`
(自有配置)和 `TunnelStats`(实时 tx/rx 计数器);`main.rs` 是一个轻量级
包装器,自定义客户端可以驱动相同的循环
- `client.rs` — 客户端核心:`Client::connect`(握手 + 在后台启动隧道),
带有实时的 `Status`、`build_auth`/`hs_obf_key` 以及
`security_warnings`(默认安全:高亮标记较弱的配置)。任何前端(CLI / GUI)复用的
引擎;它本身不持有任何加密逻辑
- `udp.rs` — 通过 `quinn-udp` 进行批量 UDP I/O(发送时使用 GSO,接收时使用 GRO),
在旧内核 / 非 Linux 系统上提供按数据包进行回退的功能;这是唯一
涉及该依赖项的模块(`batch_send` / `batch_recv` / `group_equal_sized`)
- `rekey.rs` — 解决共享套接字问题的密钥更新驱动器
(入站循环是唯一的套接字读取者;密钥更新驱动器通过 channel 接收数据)
- `tun_iface.rs` — 跨平台 TUN,带有用于测试的 mock
- `config.rs` — TOML 加载器,CLI
## 许可证
Apache 2.0 — 详见 [LICENSE](LICENSE)。标签:Rust, TUN虚拟网卡, VPN, 内核驱动, 可视化界面, 后量子密码学, 密码学, 手动系统调用, 渗透测试, 网络协议, 网络流量审计, 通知系统