16 个版本

0.5.1 2022 年 2 月 12 日
0.5.0 2022 年 2 月 10 日
0.4.5 2022 年 2 月 10 日
0.4.1 2022 年 1 月 23 日
0.2.9 2022 年 1 月 13 日

#1252网络编程

每月下载量 46

MIT 许可证

160KB
3.5K SLoC

Wireguard 网络管理器

动机/问题

情况是几个 VPS,一些家庭网络中的 IoT 设备,以及一些漫游的笔记本电脑/iPad/智能手机。到目前为止,一直使用一个相当复杂的设置,涉及 Wireguard、Openvpn,从盒子到盒子的 SSH。

始终使用 Wireguard 不是一种选择,因为这样笔记本电脑在家庭网络中会通过长路由(互联网中的某个 VPS)将流量路由到一米以外的盒子,而不是使用家庭网络内的短路径。

另一个选择可能是 tinc,但 tinc - 根据 GPL v2 许可 - 可能永远不会进入 iOS/iPadOS AppStore。所以这不是一个解决方案。

解决方案/想法

使用 Wireguard 并添加缺失的管理部分。这将

  • 启动和配置 Wireguard 设备
  • 执行密钥管理/交换
  • 自动设置路由
  • 识别更短的路径

而不是手动创建密钥(在 GUI 版本中仍然是这样),网络使用一个文件分发到所有参与者。这里是一个正在进行中的示例(文件名 net.yaml)

network:
  sharedKey: YDUBM6FhERePZ4gPlxzAbCN7K61BPjy7HApWYL+P128=
  subnet: 10.1.1.0/8

peers:
  - endPoint: 192.168.1.70:50000
    adminPort: 55555
    wgIp: 10.1.1.1
  - endPoint: 192.168.1.212:50000
    adminPort: 55555
    wgIp: 10.1.1.2

共享密钥可以使用 wg genkey 创建。

不幸的是,仍然需要定义至少一个静态对等点。

启动 alice、bob 和 charlie,例如

ALICE'S   BOX> wg_netmanager -c net.yaml -i wg0 -a 10.1.1.1  -n alice
BOB'S     BOX> wg_netmanager -c net.yaml -i wg0 -a 10.1.1.16 -n bob
CHARLIE'S BOX> wg_netmanager -c net.yaml -i wg0 -a 10.1.1.21 -n charlie

alice 可在 192.168.1.70 上访问

定义/命名法

  • 节点:网络中的参与者
  • 对等点:可以通过 Wireguard 接口直接访问的节点
  • 动态对等点:对等点的同义词
  • 静态服务器:在互联网或内网中的固定地址/端口
  • 动态服务器:任何在防火墙后面的节点(24/7)
  • 漫游客户端:任何切换 IP 地址的节点
  • 移动客户端:带数据量限制的漫游客户端

状态

节点支持

  • 配置文件中的静态服务器
  • 每个动态 DNS 的静态服务器
  • 每个命令行参数的静态服务器
  • 动态服务器
  • 漫游客户端
  • 移动客户端

操作系统支持

  • Linux
  • MacOS
  • Windows
  • iOS/iPadOS
  • Android
  • FreeBSD
  • OpenBSD
  • Openwrt Linux

Wireguard 接口

  • 内核驱动 + 命令 ip/wg
  • wireguard-go + 命令 ip/wg
  • boringtun + 命令 ip/wg
  • boringtun (嵌入) + ip

网络

  • 两个静态服务器(固定地址)之间建立连接
  • 动态节点与静态服务器之间建立连接
  • 同一子网中的两个动态节点之间建立连接
  • 使用它们的可见外部连接(即NAT穿越)建立两个动态节点之间的连接

路由

  • 设置路由以到达所有网络参与者
  • 节点的网关功能

系统集成

  • systemd
  • 基于rc的系统

管理员

  • 文本用户界面
  • REST API
  • Web UI 前端

由于在我的设置中运行良好,开发工作将现在放缓,并将更多关注于错误修复。

工作示例

我的测试设置是

             Alpha-VPS          Internet       Beta-VPS
          behind firewall ---------+---------  public IP
                                   |
                                   |
                                   |
                                 Router
                                   |
                      192.168.x.x  |
            Charlie   ------------------------  Delta

Alpha-VPA 和 Beta-VPS 使用不带 wireguard 内核驱动的旧 Linux 版本。因此使用 wireguard-go。

  1. 在所有四台机器上启动 wg_manager 后,迅速设置了三个 wireguard 连接

    • Alpha-VPS <=> Beta-VPS
    • Charlie <=> Beta-VPS
    • Delta <=> Beta-VPS

    此外,还添加了以下网关规则

    • Alpha-VPS ==> Charlie/Delta 通过网关 Beta-VPS
    • Charlie ==> Alpha-VPS/Delta 通过网关 Beta-VPS
    • Delta ==> Alpha-VPS/Charlie 通过网关 Beta-VPS
  2. 不久之后,Charlie/Delta 发现了本地连接的可能性。因此,wireguard 连接/路由更改为

    • Alpha-VPS <=> Beta-VPS

    • Charlie <=> Beta-VPS

    • Delta <=> Beta-VPS

    • Charlie <=> Delta

    • Alpha-VPS ==> Charlie/Delta 通过网关 Beta-VPS

    • Charlie ==> Alpha-VPS 通过网关 Beta-VPS

    • Delta ==> Alpha-VPS 通过网关 Beta-VPS

  3. 过一两分钟后,NAT穿越被设置。只有wireguard连接存在,没有任何网关

    • Alpha-VPS <=> Beta-VPS
    • Alpha-VPS <=> Charlie
    • Alpha-VPS <=> Delta
    • Charlie <=> Beta-VPS
    • Charlie <=> Delta
    • Delta <=> Beta-VPS

实际上,向一对一连接的趋势导致了一个新的问题。节点之间保持连接所需的生存包(以保持防火墙端口持续)的数量几乎呈平方增长……

在我的设置中不是一个大问题,但仍然需要在长远考虑中解决。

另一个工作示例

另一个设置是

             Alpha-VPS          Internet       Beta-VPS
          behind firewall ---------+---------  public IP
                                   |
                                   |
                                   |
                            =====Router 1====Masquerade+Firewall
                                   |
                      192.168.1.x  |
            Charlie   -------------+----------  Delta
                                   |
                                   |
                            =====Router 2====Masquerade+Firewall
                      192.168.2.x  |

安装

安装 rust 后,只需运行

	cargo install wg_netmanager

Linux

需要安装 wireguard-tools 和 iproute/iproute2 软件包。

如果内核驱动不存在(例如 VPS),则应安装并设置(使用 sudo)wireguard-goboringtun

Macos

需要通过 brew 安装 wireguard-tools 和 wireguard-go 等软件包。

Openwrt

需要安装 wireguard-tools 和 kmod-wireguard 软件包。

	opkg install wireguard-tools kmod-wireguard

使用

通常,需要创建一个共享密钥并将其存储在本地 network.yaml 的 sharedKey 下。可以通过以下方式完成

	wg genkey

并将结果复制到 network.yaml 中

然后修改对等列表以适应您的设置。至少需要一个具有静态地址的对等方。对于 dyndns 可达的服务器,使用主机名而不是 IP 地址。

如果子网 10.1.1.0/8 不适合您的需求,则应更改它。所有 wireguard IP 都必须包含在所选子网中。

然后,将最终的 yaml 文件复制到所有节点,并使用以下命令启动 wg_netmanager

	wg_netmanager -c network.yaml <wireguard-interface> <wireguard-ip> <name>

或 - 如果您的 sudo 需要密码

	sudo wg_netmanager -c network.yaml <wireguard-interface> <wireguard-ip> <name>

最终使用其他 --

对于不支持 wireguard 作为网络接口的 VPS,可以使用 boringtun 或 wireguard-go。wg_netmanager 将首先尝试运行 wireguard-go,然后是 boringtun。如果失败,但可以通过其他方式创建 wireguard 接口,则使用 - 命令行开关通知 wg_netmanager 关于现有 wireguard 接口。

要获取命令行选项列表,只需像平常一样使用 --help 即可。

为 wireguard 接口(-i)、地址(-a)和名称(-n)所需命令行选项可以存储在 peer.yaml 文件中,如下所示:

	name: alice
	wgIp: 10.1.1.1
	wgInterface: wg0
	existingInterface: false

最后一个选项仅在设置为 true 时才需要。

测试

使用命名空间,可以在一台 Linux 机器上模拟多个盒子。请参见示例

技术背景

wg_manager 将在两个级别上按需添加和删除路由

  • 内核路由策略使用 ip route add <ip>/32 dev <wg_dev>
  • 如果一个节点可以直接到达,可以通过在 wireguard 配置中添加一个具有允许 ip 列表的 peer 条目来实现。这个列表包括 peer 以及所有这个 peer 可以转发流量到的后续节点。

安全考虑

如果 wireguard 网络中的一个节点被破坏,那么后果是严重的。对称密钥可以被分发,任何攻击者的节点都可以加入网络。

在当前实现中,攻击者甚至可以发出以下命令

ATTACKER'S BOX> wg_netmanager -c net.yaml wg0 8.8.8.8  alice

并且所有网络参与者都将开始将所有指向 8.8.8.8 的 DNS 请求路由到攻击者的盒子。

这实际上是一个非常酷的功能,另一方面也很可怕。

更新

根据 Linux 版本的不同,ip route add 希望找到对应子网的接口。如果未能成功,则将抛出“没有这样的进程错误”。

补救措施是,wireguard 接口与 IP 和相应的子网掩码关联,而不添加路由

  ip addr add 10.1.1.1/24 dev wg0 noprefixroute

因此,在配置文件中必须指定子网。如果子网不包括 8.8.8.8,则其他节点将不接受它 - 除非定义的子网包括 8.8.8.8

许可

此 crate 的代码根据 MIT 许可。有关包含 crate 的许可信息,请检查 cargo license

经验教训

  • 花了一整天的时间弄清楚为什么 udp 套接字连接正在工作,wireguard 配置中的隧道在两个对等体上都已正确设置,但隧道却没有工作。在某个时刻,我意识到正在工作的节点都在互联网上,而失败的节点在本地子网中。重启互联网路由器解决了这个问题
  • 更新:显然,路由器不喜欢使用相同的 udp 端口,即需要在路由器防火墙中进行翻译的需求。
  • 更新 2:如果本地子网中的一个客户端重用了相同的 wireguard 端口,则无法建立通信。如果更改 wireguard 端口,它就会开始工作。

依赖项

~19–29MB
~310K SLoC