btdt1983/chameleon-pq

GitHub: btdt1983/chameleon-pq

用 Rust 编写的实验性混合后量子 VPN,结合 ML-KEM-768/X25519 密钥协商与 ML-DSA-65/Ed25519 认证,并集成数据包混淆与流量整形功能,用于学习和参考而非生产环境。

Stars: 0 | Forks: 0

Chameleon-PQ

# Chameleon-PQ [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/btdt1983/chameleon-pq/actions/workflows/ci.yml) [![crates.io](https://img.shields.io/crates/v/chameleon-pq.svg)](https://crates.io/crates/chameleon-pq) [![Release](https://img.shields.io/github/v/release/btdt1983/chameleon-pq)](https://github.com/btdt1983/chameleon-pq/releases) [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue)](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)

chameleon-gui — connected to a peer

比起使用命令行,更喜欢点击连接?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, 内核驱动, 可视化界面, 后量子密码学, 密码学, 手动系统调用, 渗透测试, 网络协议, 网络流量审计, 通知系统