使用 AB wireguard 的网络在 A 和 C 之间路由流量

使用 AB wireguard 的网络在 A 和 C 之间路由流量

我在设置 3 个节点之间的路由时遇到了一些困难。情况如下:

  • A、B 和 R 是 wireguard(wg0)对等体
    • R 是一个公共中心(vpn.example.com),IP 为 172.0.0.1
    • A 是与 R 连接的对等体,其 IP 为 172.0.0.10
    • B 是与 R 连接的对等体,其 IP 为 172.0.0.20
  • B 也连接到 IP 为 192.168.1.20 的 LAN
    • C 是同一局域网内的主机,IP 为 192.168.1.30
  • R 上的防火墙接受 wg0 和公共网络上通往 wireguard(51820/udp)的流量。

我希望路由流量以便 A 和 C 可以通信,并且从 A 可以访问 192.168.1.30。

我天真地想到以这种方式设置路由:

B# sysctl net.ipv4.ip_forward=1
A# ip route add 192.168.1.30/32 via 172.0.0.20 dev wg0
C# ip route add 172.0.0.10/32 via 192.168.1.20 dev eth0

但这不起作用:如果我tcpdump在 A 上进行流量,我可以看到从 A 到 C 的包裹:

A# tcpdump -n -l -i wg0 | grep 192
17:27:47.492184 IP 172.0.0.10 > 192.168.1.30: ICMP echo request, id 10, seq 1, length 64
17:52:36.908342 IP 172.0.0.10 > 192.168.1.30: ICMP echo request, id 10, seq 2, length 64
17:52:37.921042 IP 172.0.0.10 > 192.168.1.30: ICMP echo request, id 10, seq 3, length 64
17:52:37.932100 IP 172.0.0.10 > 192.168.1.30: ICMP echo request, id 10, seq 4, length 64

但没有答案,甚至看起来这些数据包永远无法到达 R,即使路由设置显然正确:

A# ip route get 192.168.1.30
192.168.1.30 dev wg0 src 172.0.0.20 uid 1000
    cache

所以我认为可能是 wireguard。有一个AllowedIPs选项可能有用,所以我更改了配置,如下所示:

# wg0.conf on A and B
[Interface]
Address = 172.0.0.10/24
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAA

[Peer]
PublicKey = rrrrrrrrrrrrrrrrrrrrrrrrrr
Endpoint = vpn.example.com:51820
AllowedIPs = 172.0.0.0/24, 192.168.1.30/32 # added second addr

在 RI 上将其更改为如下形式:

# wg0.conf on R, the VPN hub
[Interface]
Address = 172.0.0.1/24
PrivateKey = RRRRRRRRRRRRRRRRRRRRRRRRRR

[Peer]
PublicKey = aaaaaaaaaaaaaaaaaaaaaaaaaa
AllowedIPs = 172.0.0.10/32, 192.168.1.30/32 # added second addr

[Peer]
PublicKey = bbbbbbbbbbbbbbbbbbbbbbbbbb
AllowedIPs = 172.0.0.20/32, 192.168.1.30/32 # added second addr

并在所有主机上重新启动 wireguard。

现在我可以看到一些流量从 A 流向 R,但是似乎没有到达 B:

A# tcpdump -n -l -i wg0 | grep 192.168
...
18:11:15.421908 IP 172.0.0.10 > 192.168.1.30: ICMP echo request, id 25, seq 50, length 64
...

R# tcpdump -n -l -i wg0 | grep 192.168
...
18:11:15.421908 IP 172.0.0.10 > 192.168.1.30: ICMP echo request, id 25, seq 50, length 64
...

B# tcpdump -n -l -i wg0 | grep 192.168

B 上的路线似乎不正确:

B# ip route get 192.168.1.30
192.168.1.30 dev wg0 src 172.0.0.20 uid 30042
    cache

...事实上,我无法再从 B ping C...但这是意料之中的,因为我更改了 B 的 wireguard 配置中的路由。所以我将其回滚,B 可以 ping C,但仍然没有收到数据包。

现在我陷入了困境:我不明白发生了什么,为什么数据包没有被路由到 B。另外,我不确定从 wg0 到 B 的数据包应该如何路由到 eth0 到 C:B 是否需要路由表中的其他条目,或者是否sysctl net.ipv4.ip_forward=1

答案1

WireGuard 是一个第 3 层接口(此接口上的最低层是 IPv4(或 IPv6))。这意味着没有网关在该接口的 Linux 路由堆栈中。在这样的接口上使用任何网关参数(有效但被忽略)只会导致其含义混淆。WireGuard 本身使用对等体和AllowedIPs来扮演相关(但不相同)的角色,而路由堆栈对此一无所知。

因此,一旦创建了接口,除了已经自动添加接口地址的“LAN”路由之外,路由堆栈至少还需要这样做(重写时无需网关wg0):

R# sysctl net.ipv4.conf.wg0.forwarding=1 # will be a one-armed router
B# sysctl net.ipv4.ip_forward=1 # or else as above with eth0 + wg0
A# ip route add 192.168.1.30/32 dev wg0
C# ip route add 172.0.0.10/32 via 192.168.1.20 dev eth0

可选地,C 也可以从中受益(例如:tracerouterp_filter=1)改为获取 172.0.0.0/24 的完整路由:

C# ip route add 172.0.0.0/24 via 192.168.1.20 dev eth0

现在谈谈AllowedIPs参数。解释如下:WireGuard 加密密钥路由

在服务器配置中,每个对等体(客户端)将能够将数据包发送到具有与其相应的允许 IP 列表匹配的源 IP 的网络接口。

在服务器配置中,当网络接口想要将数据包发送到对等方(客户端)时,它会查看该数据包的目标 IP,并将其与每个对等方的允许 IP 列表进行比较,以确定将其发送到哪个对等方。

相同的AllowedIPs值既充当传入过滤器(第一个引号),又充当传出对等选择器(第二个引号)。最后一个角色是我在上面描述的与网关相关但不完全相同的角色。

不能有重叠,因为 IP 地址映射到对等体(或 none 会收到网络错误消息,例如ENOKEY( Required key not available)),再也不会出现这种情况。尝试在多个对等体上使用相同的 IP 地址是没有意义的。这只会默默地删除前一个对等体的条目,并使整体配置错误。

因此,A、R、B(实际上并不是需要,但对于很有用traceroute)之间以及 A 和 C 通过 R 之间的通信配置是:

  • 在 A:

    [Peer]
    PublicKey = rrrrrrrrrrrrrrrrrrrrrrrrrr
    [...]
    AllowedIPs = 172.0.0.0/24,192.168.1.30/32
    

    A 期望来自 R 的任何源 172.0.0.0/24(当前仅存在 R 和 B 的地址,因此可以写入它们而不是整个 /24)加上来自 R 的 192.168.1.30。

  • 在 B 上:

    [Peer]
    PublicKey = rrrrrrrrrrrrrrrrrrrrrrrrrr
    [...]
    AllowedIPs = 172.0.0.0/24
    

    B 期望 R 提供任意 172.0.0.0/24(目前只有 R 和 A 的地址存在,因此可以写入它们而不是整个 /24)。B 不会在任何地方使用 192.168.1.30:它是来自eth0(因此未经 WireGuard 验证)并且也不是通过WG0:它不应该出现在配置中(尽管如果它出现了,除了让读者感到困惑之外,这不会造成任何有害的影响)。

  • 在 R 上:

    [Peer]
    PublicKey = aaaaaaaaaaaaaaaaaaaaaaaaaa
    AllowedIPs = 172.0.0.10/32
    
    [Peer]
    PublicKey = bbbbbbbbbbbbbbbbbbbbbbbbbb
    AllowedIPs = 172.0.0.20/32,192.168.1.30/32
    

    这里不能再使用快捷方式 172.0.0.0/24:每个地址都必须出现在正确的对等点上。R 期望源 192.168.1.30 来自对等点 B,而不是来自对等点 A:它必须位于对等点 B 上,而不能位于对等点 A 上。

相关内容