跳转至内容

Rosenpass

来自 ArchWiki

Rosenpass 是一种开源的抗量子安全密钥交换协议,旨在保护 WireGuard VPN 连接免受未来量子计算威胁。Rosenpass 与 WireGuard 并行运行,将抗量子安全的共享密钥注入 WireGuard 的预共享密钥接口。所有 VPN 流量仍然只通过 WireGuard 传输,WireGuard 的二进制文件和协议保持不变,保留了 WireGuard 本身的所有安全保证。

Rosenpass 使用 Rust 编写,主要开发工作在 GitHub 上协调,并根据 MIT 和 Apache 2 许可证发布。

安装

安装 rosenpass 包,该包提供了 Rosenpass 及其辅助工具 rp

测试

为了快速测试安装是否成功,请运行 rosenpassrp 这两个工具并带有 help 命令,以显示简短的使用提示。

$ rosenpass help
$ rp help
提示 在当前版本 v0.2.2 中,如果未安装 Git,rp 会显示错误消息。您可以在没有 Git 的情况下安全地使用 rp

配置

本节介绍如何在两台设备之间设置增强型 Rosenpass WireGuard 连接。技术上来说,这两台设备之间没有区别。但为清晰起见,我们将它们命名为 serverclient

准备密钥对

每台设备都需要生成一个由密钥和公钥组成的密钥对。

为双方生成密钥

以下命令生成密钥并将它们存储在新创建的 server.rosenpass-secretclient.rosenpass-secret 目录中。

[server]$ rp genkey server.rosenpass-secret
[client]$ rp genkey client.rosenpass-secret

提取公钥

以下命令计算公钥并将它们存储在新创建的 server.rosenpass-publicclient.rosenpass-public 目录中。

[server]$ rp pubkey server.rosenpass-secret server.rosenpass-public
[client]$ rp pubkey client.rosenpass-secret client.rosenpass-public

将每个 -public 目录复制到另一方

双方都需要对方的 -public 目录,并且需要将其放置在已存在的 -secret-public 目录旁边。如果您有两台机器的 SSH 访问权限,可以使用以下命令:

[server]$ scp -r server.rosenpass-public user@client:/path/to/directory
[client]$ scp -r client.rosenpass-public user@server:/path/to/directory

这样就完成了密钥对的设置。

启动增强型 Rosenpass WireGuard VPN

在以下两个命令中,将 $SERVERIP 替换为客户端可以访问服务器的 IP 地址。这可能是一个公共可路由的 IP 地址、本地网络中的 IP 地址,甚至是回环地址 127.0.0.1

同样,将 $DEVICE 替换为服务器接收 $SERVERIP 数据包的网络设备的名称。

您可以使用以下命令查找有关网络设备和 IP 地址的信息:

[server]$ ip a

启动 VPN

serverclient 上启动 Rosenpass 和 WireGuard 进程。这将创建一个名为 rosenpass0 的 WireGuard 网络接口,允许在下一步分配内部 IP 地址,并为内部网络添加路由。

在以下两个命令中,请记住将 $SERVERIP 替换为 client 可以访问 server 的 IP 地址。

[server]# rp exchange server.rosenpass-secret \
  dev rosenpass0 \
  listen $SERVERIP:9999 \
  peer client.rosenpass-public \
  allowed-ips 192.168.21.0/24
[client]# rp exchange client.rosenpass-secret \
  dev rosenpass0 \
  peer server.rosenpass-public \
  endpoint $SERVERIP:9999 \
  allowed-ips 192.168.21.0/24

分配 IP 地址

在此示例中,我们在 VPN 内使用来自内部网络 192.168.21.0/24 的地址。您可以随意尝试其他地址,但请确保在所有必要的命令中调整 IP 地址和网络。

[server]# ip a add 192.168.21.1 dev rosenpass0
[client]# ip a add 192.168.21.2 dev rosenpass0

为 WireGuard 网络添加路由

验证路由表中是否包含内部网络 192.168.21.0/24 的条目。可以使用以下命令进行此操作:

$ ip route

其输出应包含关于 192.168.21.0/24 网络的一行,并提及 rosenpass0 接口。

…
192.168.21.0/24 dev rosenpass0 scope link
…

如果不存在这样的行,可以使用以下命令添加路由:

# ip route add 192.168.21.0/24 dev rosenpass0

请记住在服务器和客户端上都进行验证并执行此操作。

配置防火墙

不确定您是否在防火墙后面?您可以跳过此步骤,如果连接无法正常工作,可以稍后再回来。

在此示例中,服务器需要在两个端口上可访问:9999 用于 Rosenpass 连接,10000 用于 WireGuard 连接。端口 9999 在下一步使用的命令中明确配置。WireGuard 端口由 rp 工具隐式设置为 Rosenpass 端口号加一,在此示例中为 10000

配置您的防火墙,允许端口 999910000 上的传入 UDP 数据包。

如果您使用 Uncomplicated Firewall,您可以使用以下命令添加规则,以允许此示例设置所需的传入连接。请记住将 $SERVERIP 替换为客户端可以访问服务器的 IP 地址,并将 $DEVICE 替换为服务器接收 $SERVERIP 数据包的网络设备的名称。

[server]# ufw allow in on $DEVICE \
  from any to $SERVERIP \
  port 9999 \
  proto udp \
  comment 'Rosenpass'
[server]# ufw allow in on $DEVICE \
  from any to $SERVERIP \
  port 10000 \
  proto udp \
  comment 'WireGuard'

新的防火墙规则应如下所示:

server # ufw status
Status: active

To                         Action      From
--                         ------      ----
$SERVERIP 9999/udp on $DEVICE ALLOW       Anywhere                   # Rosenpass
$SERVERIP 10000/udp on $DEVICE ALLOW       Anywhere                   # WireGuard

如果您使用 nftables,您可以使用以下命令添加一条满足 Rosenpass 要求的规则。此命令假定适当的防火墙表和链名称为 filterinput;这两种名称在 nftables 的示例配置中是标准的。请记住将 $SERVERIP 替换为客户端可以访问服务器的 IP 地址,并将 $DEVICE 替换为服务器接收 $SERVERIP 数据包的网络设备的名称。

[server]# nft add rule \
  inet filter input iif $DEVICE \
  udp dport { 9999, 10000 } \
  ip daddr $SERVERIP accept

请确保保存此规则,使其在重启后仍然有效。一种方法是将其添加到 /etc/nftables.conf

验证设置

测试 Rosenpass 握手

作为第一个测试,请检查 Rosenpass 是否成功交换了共享密钥并将其作为预共享密钥 (PSK) 传递给了 WireGuard。

在服务器和客户端上,您可以运行以下命令来查看 WireGuard 当前正在为连接使用的预共享密钥。请注意,这会显示本应保密的加密密钥材料,请注意谁能够看到您计算机的屏幕。

# wg show rosenpass0 preshared-keys

输出应显示一行,由两个 base64 编码的字符串组成,用空格分隔。第二个字符串是预共享密钥。这在两台机器上应该是相同的。Rosenpass 大约每两分钟更改一次。

q1ySvWXjsS2l0Apu2f9YZLw7pLT4+QXfIZVTpMBO01I=    (redacted)

同样,在服务器和客户端上,您可以显示 WireGuard 连接的状态。

# wg show rosenpass0

在客户端上,您应该会看到类似以下的输出,其中 $SERVERIP 与之前配置的 IP 地址匹配。

interface: rosenpass0
  public key: 1NQJ1iObOnkkWlqDU6bhqGPEjCIIvKTKjI10XE0t7DA=
  private key: (hidden)
  listening port: 52922

peer: q1ySvWXjsS2l0Apu2f9YZLw7pLT4+QXfIZVTpMBO01I=
  preshared key: (hidden)
  endpoint: $SERVERIP:10000
  allowed ips: 192.168.21.0/24

而在服务器上,您应该会看到类似以下的输出,WireGuard 监听端口为 10000

interface: rosenpass0
  public key: q1ySvWXjsS2l0Apu2f9YZLw7pLT4+QXfIZVTpMBO01I=
  private key: (hidden)
  listening port: 10000

peer: 1NQJ1iObOnkkWlqDU6bhqGPEjCIIvKTKjI10XE0t7DA=
  preshared key: (hidden)
  allowed ips: 192.168.21.0/24

显示的服务器公钥应列为客户端对端 (peer) 的 ID,反之亦然。

如果您想持续监视 WireGuard 隧道和其预共享密钥的当前状态,可以在客户端和服务器上运行以下命令;这在调试时很有用,例如,查看双方是否保持使用相同的预共享密钥并同步交换。此命令将上述两个命令组合起来,每 2 秒重复一次。

# watch 'wg show all; wg show all preshared-keys'

测试 WireGuard 连接

您可以通过从客户端 ping 服务器的内部 IP 地址,反之亦然来测试 WireGuard 连接。

[server]$ ping 192.168.21.2
[client]$ ping 192.168.21.1

从服务器 ping 到客户端的连接可能只有在从客户端 ping 到服务器的连接启动后才能成功。

一切完成,ping 测试也成功了吗?

Rosenpass 现在将大约每两分钟为 WireGuard 生成一个新的 PSK 密钥,并使 WireGuard VPN 连接免受后量子计算机攻击。

参见