iptables:如何将 UDP 和 TCP 端口转发到 wireguard VPN 连接后面的服务器

iptables:如何将 UDP 和 TCP 端口转发到 wireguard VPN 连接后面的服务器

因此,我有一台运行 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 --followWireguard 似乎由于以下原因丢弃了数据包:

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-quickAllowedIPs认为应该添加路由并通过 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 接口和路由规则。

相关内容