免责声明:转自 stackoverflow:https://stackoverflow.com/questions/67917278/site2site-wireguard-with-docker-routing-problems
我正在尝试让两个容器在两个 RPI 上运行,充当网络 1 和网络 2 之间的站点到站点 VPN。
通过以下设置,我可以 ping 通从容器内部彼此网络:
- 从 docker 容器 1 我可以 ping 地址 192.168.1.1
- 从 docker 容器 2 我可以 ping 地址 192.168.10.1
但是如果我尝试从 System1 主机 (192.168.10.100) ping 192.168.1.1,则会遇到错误(请参见下图来直观地了解我正在尝试做什么)。
我知道我必须在 system1 主机(192.168.10.100)上添加一条静态路由,以将 192.168.1.0/24 的流量引导通过 wireguard 容器(172.17.0.5),因此我运行:
$i p route add 192.168.1.0/24 via 172.17.0.5
$ ip route
default via 192.168.10.1 dev eth0 proto dhcp src 192.168.10.100 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.18.0.0/16 dev br-e19a4f1b7646 proto kernel scope link src 172.18.0.1 linkdown
172.19.0.0/16 dev br-19684dacea29 proto kernel scope link src 172.19.0.1
172.20.0.0/16 dev br-446863cf7cef proto kernel scope link src 172.20.0.1
172.21.0.0/16 dev br-6800ed9b4dd6 proto kernel scope link src 172.21.0.1 linkdown
172.22.0.0/16 dev br-8f8f439a7a28 proto kernel scope link src 172.22.0.1 linkdown
192.168.1.0/24 via 172.17.0.5 dev docker0
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.100
192.168.10.1 dev eth0 proto dhcp scope link src 192.168.10.100 metric 100
但 ping 192.168.1.1 仍然失败。
通过在容器 2 上运行 tcpdump,我看到一些数据包确实到达了容器:
root@936de7c0d7eb:/# tcpdump -n -i any
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
10:11:19.885845 IP [publicIPsystem1].56200 > 172.17.0.6.56100: UDP, length 128
10:11:30.440764 IP 172.17.0.6.56100 > [publicIPsystem1].56200: UDP, length 32
10:11:35.480625 ARP, Request who-has 172.17.0.1 tell 172.17.0.6, length 28
10:11:35.480755 ARP, Reply 172.17.0.1 is-at 02:42:24:e5:ac:38, length 28
所以我猜测这不是系统 1 上的路由问题。
谁能告诉我如何进一步诊断?
编辑1:
我做了以下测试:
- 在容器 2 上运行“tcpdump -ni any”
- 从系统 1(从主机系统)发送 ping 命令“ping -c 1 192.168.1.1”。
在容器 2 上,tcpdump 记录了以下内容:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
15:04:47.495066 IP [publicIPsystem1].56200 > 172.17.0.3.56100: UDP, length 128
15:04:58.120761 IP 172.17.0.3.56100 > [publicIPsystem1].56200: UDP, length 32
- 从容器(容器内)发送 ping 命令 'ping -c 1 192.168.1.1 。
在容器 2 上,tcpdump 记录了以下内容:
# tcpdump -ni any
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
15:05:48.120717 IP [publicIPsystem1].56200 > 172.17.0.3.56100: UDP, length 128
15:05:48.120871 IP 10.13.18.2 > 192.168.1.1: ICMP echo request, id 747, seq 1, length 64
15:05:48.120963 IP 172.17.0.3 > 192.168.1.1: ICMP echo request, id 747, seq 1, length 64
15:05:48.121955 IP 192.168.1.1 > 172.17.0.3: ICMP echo reply, id 747, seq 1, length 64
15:05:48.122054 IP 192.168.1.1 > 10.13.18.2: ICMP echo reply, id 747, seq 1, length 64
15:05:48.122246 IP 172.17.0.3.56100 > [publicIPsystem1].56200: UDP, length 128
15:05:53.160617 ARP, Request who-has 172.17.0.1 tell 172.17.0.3, length 28
15:05:53.160636 ARP, Request who-has 172.17.0.3 tell 172.17.0.1, length 28
15:05:53.160745 ARP, Reply 172.17.0.3 is-at 02:42:ac:11:00:03, length 28
15:05:53.160738 ARP, Reply 172.17.0.1 is-at 02:42:24:e5:ac:38, length 28
15:05:58.672032 IP [publicIPsystem1].56200 > 172.17.0.3.56100: UDP, length 32
因此,似乎根据我目前遗漏的某些东西,数据包与容器 2 的处理方式不同。这可能是 iptables 的问题吗?
站点 1 | 站点 2 | |
---|---|---|
网络 1 IP 范围 | 192.168.10.0/24 | 192.168.1.0/24 |
主机系统地址 | 192.168.10.100 | 192.168.1.100 |
桥接 docker0 范围 | 172.17.0.0/16 | 172.17.0.0/16 |
集装箱地址 | 172.17.0.5 | 172.17.0.6 |
系统 1-wg0.conf
[Interface]
Address = 10.13.18.2
PrivateKey = *privatekey*
ListenPort = 56200
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = *publickey*
Endpoint = *system2address*:56100
AllowedIPs = 10.13.18.1/32 , 192.168.1.0/24
系统 2——wg0.conf
[Interface]
Address = 10.13.18.1
ListenPort = 56100
PrivateKey = *privatekey*
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
# peer_casaleuven
PublicKey = *publickey*
AllowedIPs = 10.13.18.2/32 , 192.168.10.0/24
Endpoint = *system1address*:56200
答案1
这看起来像是一个路由问题。
192.168.1.0/24 via 172.17.0.5 dev docker0
此路由未提示首选源地址。因此,主机自然会选择最接近的匹配地址:172.17.0.1,因为它是docker0。172.17.0.1 不在对等方的 WireGuard 的 AllowedIPs 列表中(也不应该在列表中),因此将被 WireGuard 拒绝。如果它没有被拒绝,那么对等方中无论如何都会存在路由问题,因为两个独立的 LAN 使用相同的 IP 地址块。
尝试这个
系统 1
ip route replace 192.168.1.0/24 via 172.17.0.5 dev docker0 src 192.168.10.100
系统 2
ip route replace 192.168.10.0/24 via 172.17.0.6 dev docker0 src 192.168.1.100
请注意,在进行此次调整之前,这应该不会影响其余的 LAN,只会影响两个 Docker 主机系统。