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 |
|
#1252 在 网络编程
每月下载量 46
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。
-
在所有四台机器上启动 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
-
不久之后,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
-
-
过一两分钟后,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-go
或 boringtun
。
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