quincy-rs/quincy
GitHub: quincy-rs/quincy
一款基于 QUIC 协议并支持后量子密码学的 VPN 实现,涵盖跨平台客户端与服务端。
Stars: 319 | Forks: 22
# Quincy
[](https://crates.io/crates/quincy)
[](https://hub.docker.com/r/m0dex/quincy)
[](https://docs.rs/quincy/)
[](https://github.com/M0dEx/quincy/actions?query=workflow%3ACI)
[](https://codecov.io/github/quincy-rs/quincy)
[](LICENCE)
[](https://matrix.to/#/#quincy:matrix.org)
Quincy 是一个 VPN 客户端和服务器端实现,使用 [QUIC](https://en.wikipedia.org/wiki/QUIC) 协议,并支持前量子、混合和后量子密码学。
## 目录
- [支持的平台](#supported-platforms)
- [安装](#installation)
- [Cargo](#cargo)
- [Docker](#docker)
- [安装程序](#installers)
- [从源码构建](#building-from-sources)
- [环境要求](#requirements)
- [构建特性](#build-features)
- [用法](#usage)
- [客户端 (CLI)](#client-cli)
- [客户端 (GUI)](#client-gui)
- [服务器端](#server)
- [用户](#users)
- [架构](#architecture)
- [协议模式](#protocol-modes)
- [TLS](#tls)
- [Noise](#noise)
- [指标](#metrics)
- [证书管理](#certificate-management)
- [服务器证书](#server-certificate)
- [客户端证书](#client-certificate)
## 支持的平台
- [X] Windows (x86_64),使用 [Wintun](https://www.wintun.net/)
- [X] Linux (x86_64, aarch64)
- [X] FreeBSD (x86_64, aarch64)
- [X] MacOS (aarch64)
## 安装
以下平台提供二进制文件和安装程序:
- Windows (x86_64)
- Linux (x86_64)
- FreeBSD (x86_64)
- MacOS (aarch64)
### Cargo
使用 cargo,只需一条简单的命令即可安装任何已发布的版本:
```
# CLI 客户端二进制文件
cargo install --locked quincy-client
# CLI 服务端二进制文件
cargo install --locked quincy-server
# 身份管理工具
cargo install --locked quincy-identity
# 客户端 GUI 二进制文件
cargo install --locked quincy-gui
```
### Docker
可以在 [Docker Hub](https://hub.docker.com/r/m0dex/quincy) 上获取不同版本的 Docker 镜像:
- `m0dex/quincy:latest`:Quincy 的最新版本
- `m0dex/quincy:`:Quincy 的特定版本
**注意:由于 Docker 网络的工作原理,无法使用 `dns_servers` 配置选项**
要运行客户端/服务器端,你需要添加一个包含配置文件的卷,并添加所需的能力(capabilities):
```
docker run
--rm # remove the container after it stops
--cap-add=NET_ADMIN # needed for creating the TUN interface
--device=/dev/net/tun # needed for creating the TUN interface
-p "55555:55555" # server port-forwarding
-v :/etc/quincy # directory with the configuration files
m0dex/quincy:latest # or any of the other tags
quincy-server --config-path /etc/quincy/server.toml
```
### 安装程序
可以从 [GitHub releases](https://github.com/quincy-rs/quincy/releases) 下载 GUI 客户端的特定平台安装程序:
- **Windows**: NSIS 安装程序 (`.exe`)
- **macOS**: DMG 磁盘映像 (`.dmg`)
- **Linux**: Debian 软件包 (`.deb`) 和 AppImage (`.AppImage`)
**macOS 用户注意**:安装后,您可能需要移除隔离属性才能启动应用:
```
xattr -d com.apple.quarantine /Applications/Quincy.app
```
## 从源码构建
由于 Quincy 不依赖任何非 Rust 库,因此构建过程非常简单:
```
cargo build
```
如果你还想构建带有优化的 Quincy release 模式,请添加 `--release` 开关:
```
cargo build --release
```
生成的二进制文件可以在 `target/debug` 和 `target/release` 目录中找到。
### 环境要求
由于依赖 `aws-lc-rs` 密码模块,因此需要一个 C 编译器(Clang 或 GCC)。
有关更多信息,请参阅 [aws-lc-rs 构建说明](https://github.com/aws/aws-lc-rs/blob/main/aws-lc-rs/README.md#Build)。
### 构建特性
- `jemalloc`:在 UNIX 系统上使用 jemalloc 内存分配器以提高性能 [默认值:**启用**]
- `offload`:为 Linux 上的 TUN 接口启用 GSO/GRO 卸载优化 [默认值:**启用**]
- `metrics`:在服务器端启用 Prometheus 指标端点(参见 [指标](#metrics)) [默认值:**禁用**]
## 用法
Quincy 根据预期用途提供了几个二进制文件:
- `quincy-client`:VPN 客户端 CLI
- `quincy-server`:VPN 服务器端 CLI
- `quincy-identity`:用于为 TLS 和 Noise 模式生成密钥和证书的实用工具
- `quincy-client-gui`:VPN 客户端 GUI
- `quincy-client-daemon`:VPN 客户端守护进程(后台特权服务)
### 客户端 (CLI)
Quincy 客户端需要一个单独的配置文件,示例可以在 [`examples/client.toml`](examples/client.toml) 中找到。
有关客户端配置文件字段的文档可以在[这里](https://docs.rs/quincy/latest/quincy/config/struct.ClientConfig.html)找到。
配置文件准备好后,可以使用以下命令启动客户端:
```
quincy-client --config-path examples/client.toml
```
默认情况下,路由被设置为从服务器接收到的地址和网络掩码。
现在必须手动设置任何额外的路由。
### 客户端 (GUI)
Quincy 客户端 GUI 是跨平台的,使用 [iced](https://iced.rs/) 构建。
它提供了一个简单的界面,用于管理和连接/断开多个客户端实例,以及查看连接统计信息。
所有配置文件都存储在 `~/.config/quincy`(Linux, macOS)或 `%APPDATA%\quincy`(Windows)中。
GUI 以非特权模式运行,并使用单独的可执行文件(`quincy-client-daemon`)来处理特权操作,例如创建 TUN 接口和设置路由。
_当前实现此功能的方式使用了相当原始的权限提升命令,用户体验不佳。这将在未来进行更改和改进。_
### 服务器端
Quincy 服务器端需要一个单独的配置文件,示例可以在 [`examples/server.toml`](examples/server.toml) 中找到。
有关服务器端配置文件字段的文档可以在[这里](https://docs.rs/quincy/latest/quincy/config/struct.ServerConfig.html)找到。
配置文件准备好后,可以使用以下命令启动客户端:
```
quincy-server --config-path examples/server.toml
```
**请记住,[`examples/cert/server_cert.pem`](examples/cert/server_cert.pem) 中预先生成的证书
是自签名的,并且使用主机名 `quincy`。应将其替换为正式的证书,
该证书可以使用[证书管理](#certificate-management)部分中的说明生成。**
### 用户
Quincy 在 QUIC 握手层使用公钥(Noise)或证书指纹(TLS)对客户端进行身份验证。不涉及任何密码。
用户通过服务器配置中 `users_file` 字段引用的 TOML 文件进行管理(示例可在 [`examples/users.toml`](examples/users.toml) 中找到):
```
[users.alice]
# 授权给该用户的 Base64 编码的 Noise 公钥
authorized_keys = [
"base64-encoded-x25519-public-key",
]
# 授权给该用户的 TLS 证书指纹
authorized_certs = [
"sha256:2dba01529210e4e828265d56329df1b85a8f9aedccdd3fef67ab502b57cb0029",
]
[users.bob]
authorized_keys = []
authorized_certs = [
"sha256:abc123...",
]
```
每个用户可以拥有任意数量的已授权 Noise 公钥和 TLS 证书指纹。服务器端通过将连接客户端的握手身份与这些条目进行匹配来识别它们。
要生成此文件的值,请使用 `quincy-identity` 实用工具:
```
# 从私钥派生 Noise 公钥
quincy-identity noise genkey | quincy-identity noise pubkey
# 获取 TLS 客户端证书的指纹
quincy-identity tls fingerprint --cert client_cert.pem
```
## 架构
Quincy 使用由 [`quinn`](https://github.com/quinn-rs/quinn) 实现的 QUIC 协议,在客户端和服务器端之间创建加密隧道。
客户端身份验证在 QUIC 握手本身期间执行,可以通过双向 TLS(证书指纹验证)或通过 Noise IK 握手(静态公钥验证)来完成。握手后不需要额外的身份验证协议。
握手完成后,服务器端识别客户端,从其地址池中分配一个隧道 IP,并通过单向 QUIC 流将其发送给客户端。然后,客户端使用分配的地址创建一个 TUN 接口。
隧道建立后,数据传输通过不可靠的 QUIC 数据报进行(具有更低的延迟和开销)。为每个客户端生成一个连接任务,在 TUN 接口和 QUIC 连接之间转发数据包。
使用 [`tokio`](https://github.com/tokio-rs/tokio) runtime 提供高效且可扩展的实现。
### 架构图
[](docs/architecture_diagram.svg)
## 协议模式
Quincy 支持 QUIC 隧道的两种加密协议模式:TLS 和 Noise。在服务器端和客户端配置文件的 `[protocol]` 部分中选择该模式。
### TLS
TLS 1.3 是默认的协议模式。它在服务器端和客户端身份验证中均使用双向 TLS (mTLS),并支持三种密钥交换算法:
- `Standard`:ECDH (X25519)
- `Hybrid`:X25519 + ML-KEM-768
- `PostQuantum`:ML-KEM-768
TLS 模式要求服务器端和客户端都有证书和私钥。服务器端通过将客户端证书的 SHA-256 指纹与 [用户文件](#users) 中的条目进行匹配来验证客户端身份。有关生成和配置证书的详细信息,请参见 [证书管理](#certificate-management)。
证书和密钥可以从文件加载,也可以在配置中直接作为 PEM 字符串提供。当您希望配置在多行显示证书时,TOML 多行基本字符串(`"""..."""`)非常适合 PEM 数据。
**服务器端**
```
[protocol]
mode = "tls"
key_exchange = "hybrid"
certificate_file = "server_cert.pem"
certificate_key_file = "server_key.pem"
# 或使用内联 PEM 字符串:
# certificate = """
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# """
# certificate_key = """
# -----BEGIN PRIVATE KEY-----
# ...
# -----END PRIVATE KEY-----
# """
```
**客户端**
```
[protocol]
mode = "tls"
key_exchange = "hybrid"
trusted_certificate_paths = ["server_cert.pem"]
# 或信任内联 PEM 字符串:
# trusted_certificates = [
# """
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# """
# ]
client_certificate_file = "client_cert.pem"
client_certificate_key_file = "client_key.pem"
# 或使用内联 PEM 字符串:
# client_certificate = """
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# """
# client_certificate_key = """
# -----BEGIN PRIVATE KEY-----
# ...
# -----END PRIVATE KEY-----
# """
```
### Noise
Noise 模式使用 Noise IK 握手模式而不是 TLS。服务器端和客户端都拥有静态密钥对,并且在握手开始之前,双方都知道对方的公钥。这有两个主要优点:
- **无需证书**:在管理 PKI 或从 CA 获取证书不切实际的环境中,部署更加简单。
- **改进的检测规避**:流量不包含标准的 TLS ClientHello,使得 DPI 系统更难对其进行指纹识别和阻止。
服务器端通过将连接客户端的公钥与 [用户文件](#users) 中的条目进行匹配来识别它们。支持两种密钥交换算法:
- `Standard`:X25519
- `Hybrid`:X25519 + ML-KEM-768
#### 密钥管理
使用 `quincy-identity`,您可以为服务器端和客户端生成密钥对:
```
# 生成私钥
quincy-identity noise genkey
# 从 stdin 上的私钥派生匹配的公钥
quincy-identity noise pubkey
# 对于混合密钥交换,请向两个命令传递 --key-exchange hybrid
quincy-identity noise genkey --key-exchange hybrid
quincy-identity noise genkey --key-exchange hybrid | quincy-identity noise pubkey --key-exchange hybrid
```
服务器端和每个客户端都需要自己的密钥对。将密钥放在相应的配置文件中:
**服务器端**
```
[protocol]
mode = "noise"
key_exchange = "standard"
private_key = ""
```
**客户端**
```
[protocol]
mode = "noise"
key_exchange = "standard"
server_public_key = ""
private_key = ""
```
**注意:`key_exchange` 值必须在服务器端和客户端上保持一致。**
## 指标
服务器端可以暴露与 Prometheus 兼容的指标端点。此功能是可选的,需要启用 `metrics` 构建特性:
```
cargo build -p quincy-server --features metrics
```
即使使用该特性构建,该端点默认情况下仍处于禁用状态。要启用它,请在服务器端配置文件中添加 `[metrics]` 部分:
```
[metrics]
# metrics 端点是否处于活动状态(默认值:false)
enabled = true
# HTTP 服务器的绑定地址(默认值:127.0.0.1)
address = "127.0.0.1"
# HTTP 服务器的绑定端口(默认值:9090)
port = 9090
# 每连接状态更新之间的间隔秒数(默认值:5)
# reporting_interval_s = 5
```
一旦运行,可以通过 `GET http://:/metrics` 以 Prometheus 文本展示格式获取指标。
每个连接报告以下指标,每个指标都标有 `user`(已认证的用户名)和 `connection`(分配的隧道 IP):
| 指标 | 类型 | 描述 |
|---|---|---|
| `quincy_bytes_tx_total` | Counter | 传输到客户端的总字节数 |
| `quincy_bytes_rx_total` | Counter | 从客户端接收的总字节数 |
| `quincy_datagrams_tx_total` | Counter | 传输到客户端的 UDP 数据报总数 |
| `quincy_datagrams_rx_total` | Counter | 从客户端接收的 UDP 数据报总数 |
| `quincy_connection_rtt_seconds` | Gauge | QUIC 路径的平滑往返时间 |
| `quincy_connection_duration_seconds` | Gauge | 自连接建立以来的时间 |
_指标仅在服务器端可用。客户端和 GUI 不暴露 Prometheus 端点。_
## 证书管理
TLS 模式使用双向 TLS,因此服务器端和每个客户端都需要自己的证书和私钥。
### 服务器证书
在设置服务器证书时,有几种选项可供选择。
#### 由受信任的 CA 签名的证书
这是管理服务器证书的*正规*方法。
您可以向具有全球受信任 CA(Let's Encrypt, GoDaddy, ...)的服务请求/购买证书,也可以生成自己的证书颁发机构,然后签署终端证书。
如果您拥有由全球受信任 CA 签名的证书,只需将其添加到服务器配置文件中并运行 Quincy 即可。客户端将信任该证书,因为签名证书很可能在系统的受信任根证书存储中。
如果您拥有由自己(自签名)CA 签名的证书,请按照上述步骤操作,并将您的 CA 证书添加到客户端配置文件中。
您可以使用 [mkcert](https://github.com/FiloSottile/mkcert) 生成自己的 CA 证书,并使用它签署终端证书。
#### 自签名证书
这是一种更简单的设置方式,可能被家庭实验室管理员用于测试。
生成可用于 Quincy 的自签名服务器证书的步骤:
1. 生成私钥(我的证书使用 ECC,但 RSA 也可以)
```
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:secp384r1 -out
```
2. 生成证书签名请求
```
openssl req -new -key -out
```
```
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:XX
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:quincy
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```
3. 创建一个包含以下内容的 v3 扩展配置文件(在 `subjectAltName` 字段中填写客户端将连接到的主机名/IP)
```
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign
subjectAltName = DNS:quincy
issuerAltName = issuer:copy
```
4. 签署您的证书
```
openssl x509 -req -in cert.csr -signkey -out -days 365 -sha256 -extfile
```
5. 将证书添加到服务器配置文件中。
**服务器端**
```
[protocol]
mode = "tls"
# 用于 TLS 的证书路径
certificate_file = "server_cert.pem"
# 或者是 PEM 编码的证书链
# certificate = """
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# """
# 用于 TLS 的证书密钥路径
certificate_key_file = "server_key.pem"
# 或者是 PEM 编码的私钥
# certificate_key = """
# -----BEGIN PRIVATE KEY-----
# ...
# -----END PRIVATE KEY-----
# """
```
### 客户端证书
生成客户端证书最简单的方法是使用 `quincy-identity`:
```
quincy-identity tls gencert --out-cert client_cert.pem --out-key client_key.pem --cn "alice"
```
这将打印出证书的 SHA-256 指纹,您需要将其添加到 [用户文件](#users) 中。您也可以稍后获取该指纹:
```
quincy-identity tls fingerprint --cert client_cert.pem
```
将证书和密钥添加到客户端配置文件中,同时添加服务器端信任的证书:
**客户端**
```
[protocol]
mode = "tls"
# 服务器可以使用或由其签名证书的受信任证书文件路径列表
trusted_certificate_paths = ["server_cert.pem"]
# 作为 PEM 字符串的受信任证书列表
# trusted_certificates = [
# """
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# """
# ]
# 用于双向 TLS 身份验证的客户端证书路径
client_certificate_file = "client_cert.pem"
# 或者是 PEM 编码的客户端证书链
# client_certificate = """
# -----BEGIN CERTIFICATE-----
# ...
# -----END CERTIFICATE-----
# """
# 客户端证书私钥的路径
client_certificate_key_file = "client_key.pem"
# 或者是 PEM 编码的私钥
# client_certificate_key = """
# -----BEGIN PRIVATE KEY-----
# ...
# -----END PRIVATE KEY-----
# """
```
## 目录
- [支持的平台](#supported-platforms)
- [安装](#installation)
- [Cargo](#cargo)
- [Docker](#docker)
- [安装程序](#installers)
- [从源码构建](#building-from-sources)
- [环境要求](#requirements)
- [构建特性](#build-features)
- [用法](#usage)
- [客户端 (CLI)](#client-cli)
- [客户端 (GUI)](#client-gui)
- [服务器端](#server)
- [用户](#users)
- [架构](#architecture)
- [协议模式](#protocol-modes)
- [TLS](#tls)
- [Noise](#noise)
- [指标](#metrics)
- [证书管理](#certificate-management)
- [服务器证书](#server-certificate)
- [客户端证书](#client-certificate)
## 支持的平台
- [X] Windows (x86_64),使用 [Wintun](https://www.wintun.net/)
- [X] Linux (x86_64, aarch64)
- [X] FreeBSD (x86_64, aarch64)
- [X] MacOS (aarch64)
## 安装
以下平台提供二进制文件和安装程序:
- Windows (x86_64)
- Linux (x86_64)
- FreeBSD (x86_64)
- MacOS (aarch64)
### Cargo
使用 cargo,只需一条简单的命令即可安装任何已发布的版本:
```
# CLI 客户端二进制文件
cargo install --locked quincy-client
# CLI 服务端二进制文件
cargo install --locked quincy-server
# 身份管理工具
cargo install --locked quincy-identity
# 客户端 GUI 二进制文件
cargo install --locked quincy-gui
```
### Docker
可以在 [Docker Hub](https://hub.docker.com/r/m0dex/quincy) 上获取不同版本的 Docker 镜像:
- `m0dex/quincy:latest`:Quincy 的最新版本
- `m0dex/quincy:标签:QUIC, Rust, VPN, 可视化界面, 后量子密码学, 安全监控, 渗透测试, 网络工具, 网络流量审计, 网络通信, 虚拟专用网, 请求拦截, 通知系统