因此,我有一台运行 Debian bullseye 的 VPS(KVM)服务器,具有公共 IP。该服务器还运行着一个 wireguard 服务器。在家里,我还有另一台服务器(位于 NAT 后面),该服务器带有一个连接到我的 VPS 的 wireguard 客户端。隧道已启动并运行,这意味着我可以通过 wireguard VPN 正常通信。
+----------------------------------+ +-------------------------------
| Homeserver (behind NAT) | | VPS (KVM) with public IP |
| 192.168.1.10 | | 1.2.3.4 |
| +------------------------| |--------------------+ |
| | wg-homeserver | - - - - - - | wg-vps | |
| | 192.168.200.2 | | 192.168.200.1 | |
| +------------------------| |--------------------+ |
| | | |
+----------------------------------+ +------------------------------+
我的家庭服务器运行了许多监听端口(在所有 IP 地址上)的 docker 容器,这意味着这些端口可以从 192.168.1.0/24 访问。我现在需要在我的 VPS 的公共 IP 地址上转发一个 TCP 和一个 UDP 端口,并通过 wireguard 链接将流量转发到我的家庭服务器上的相同端口:
1.2.3.4:10000/tcp -> 192.168.200.2:10000/tcp
1.2.3.4:10001/udp -> 192.168.200.2:10001/udp
两台机器都启用了 IP 转发,即cat /proc/sys/net/ipv4/ip_forward
显示1
。
为了转发 TCP 端口,我有以下规则:
iptables -A FORWARD -d 192.168.200.2/32 -i wg-vps -p tcp --dport 10000 -j ACCEPT
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 10000 -j DNAT --to-destination 192.168.200.2:10000
当我尝试时,ssh -p 10000 1.2.3.4
我没有看到任何被记录的数据包wireguard -i wg-vps
。我尝试了许多其他方法,但无法弄清楚我做错了什么或遗漏了什么。
无论如何,对于 UDP 端口,我创建了此规则,并取得了一些成功:
iptables -t nat -A PREROUTING -d 1.2.3.4/32 -i eth0 -p udp --dport 10001 -j DNAT --to-destination 192.168.200.2:10001
这是我发送 udp 测试包的方式:
echo -n test | nc -4 -u 1.2.3.4 10001
当我执行此操作时,我可以tcpdump -i wg-vps
在我的 VPS 日志上看到此内容(4.5.6.7
这是我的公共 IP 地址):
11:35:47.497622 IP 4.5.6.7.43357 > 192.168.200.2.10001: UDP, length 4
它似乎在尝试做正确的事情,接收数据包,将目的地更新为192.168.200.2
,然后将其放到 wireguard 接口上wg-vps
。但tcpdump -i wg-homeserver
我的家庭服务器上从未显示此数据包到达。
事实上,我注意到,当我watch ip -s link show wg-homeserver
在家庭服务器上时,每次我向该端口发送 udp 数据包时,RX 错误都会增加 1。所以某物一路到达那里,但无论它是什么,它都没有显示出来tcpdump
,似乎被丢弃在下面的某个地方。这很奇怪,因为 wireguard 链路上的 UDP 和 TCP 在两个方向上都可以正常工作。
据我所知,tcpdump
显示的是 iptables 之前的数据包,所以我的猜测是,即使数据包似乎已写入 wireguard 接口,但它在某处被丢弃。
更新: 好的,我找到了一种启用 wireguard 日志记录的方法:
echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
当跟踪日志时,dmesg --follow
Wireguard 似乎由于以下原因丢弃了数据包:
wireguard: wg-homeserver: Packet has unallowed src IP (4.5.6.7) from peer 20 (xxxxxx)
所以我认为这意味着它不喜欢源地址是请求来源的原始地址。我不想做 SNAT,所以我想我只需要以某种方式教它应该允许任何源地址。
事实证明这是我的 wireguard 配置部分AllowedIPs
中的设置[Peer]
。这解决了该问题:
AllowedIPs = 0.0.0.0/0, ::0/0
在此之前,我已经放置了与部分中类似的接口掩码[Interface]
,但没有意识到这会限制数据包的源地址。
但是,这会劫持所有流量并尝试通过 wireguard 链接路由,因为wg-quick
它AllowedIPs
认为应该添加路由并通过 VPN 重定向所有流量。这显然不是我们想要的,但幸运的是有一个解决方案:添加Table = off
到[Interface]
部分将阻止这种情况。
答案1
查看您的规则表以了解传出的数据包在家庭服务器上是如何路由的。wg-quick 将添加一些规则。
ip rule show
对我来说,我必须删除 wg-quick 生成的一些规则(这使得它将所有数据包转发到 wg),然后添加转发所需端口的规则。您可以从上面的命令中看到 wg 表号。
ip -4 rule add sport 80 table XXXXX
ip -4 rule add sport 443 table XXXXX
上述方法在一段时间内有效。但是当 dhcp 租约到期或 lan 电缆断开并重新连接时,systemd-networkd 会删除自定义规则。因此我完全删除了 wg-quick,并使用 systemd-networkd 来配置 wg 接口和路由规则。