使用基于源的路由无需 SNAT/伪装的 VPS 端口转发?

使用基于源的路由无需 SNAT/伪装的 VPS 端口转发?

我正在尝试使用 VPS 进行测试,通过 VPN 隧道将 80,443 端口转发到本地 Web 服务器,同时保持原始源公共 IP 不变。这里的主要问题是路由,因为边缘路由设备实际上会看到 2 个带有公共 IP 的接口(真正的 WAN 和 VPN 接口)。

显然,简单的解决方案是仅 SNAT 流量穿过 VPN 隧道,但我想深入了解 Web 流量的真正来源,加上我做的 NAT 越多,引入系统的开销就越多。此外,我避免在 VPS 上放置任何反向代理,因为我拒绝在遍历 VPS 时随时解密网络流量。

现在进行到目前为止的测试:使用的 IP:Web SRV:192.168.0.2,VPS Wireguard 地址:192.168.200.1,路由器 Wireguard 地址:192.168.200.2。

我设置了一个虚拟测试网络,其中有几个 Debian 11 机器用作 VPS 服务器、本地路由器和 Web 服务器。

在 VPS 上,DNAT 流量进入端口 80,443 上的接口:

iptables -t nat -A PREROUTING -i eth0 -p tcp -m multiport –dports 80,443 -j DNAT –to-destination 192.168.0.2

我已经设置了 sysctl.conf 以启用 ipv4 转发。我在 VPS 上有一个静态路由,指示从哪里到达 192.168.0.2:

ip route add 192.168.0.2/32 via 192.168.200.2 dev wg0

在本地路由器上,我在网上发现了一些基于接口的基于回复的规则:

echo 200 vpsrt >> /etc/iproute2/rt_tables

ip rule add from 192.168.200.2 table vpsrt prio 1
ip route add default via 192.168.200.1 dev wg0 table vpsrt

由于 VPN 隧道位于路由器上,Web 服务器已配置其默认网关,因此本地路由器和 Web 服务器之间的返回流量根本不会改变。

VPS 上的 wg0.conf(充当服务器):

[Interface]
PrivateKey=*
Address=192.168.200.1/30
ListenPort=50000

[Peer]
PublicKey=*
AllowedIPs=192.168.200.2/32,192.168.0.2/32

路由器上的 wg0.conf(充当客户端):

[Interface]
Address=192.168.200.2/32
PrivateKey=*

[Peer]
Endpoint=PUBIPVPS:50000
PublicKey=*
AllowedIPs=172.20.200.0/30

我已经验证了 Wireguard 隧道的工作原理。我可以分别在每个设备上 ping 192.168.200.1 和 .2,并且 wg show 表示握手已完成并且双向数据正在流动。

进行一些 PCAP,通过 VPS 的流量是正确的。 VPS 上 wg0 上的 Tcpdump 显示地址为 192.168.0.2 端口 443 的数据包。VPS 上的 WG Show 表示其传输 1.3Kb,但路由器上的 WG Show 表示仅收到 500 字节(测试 ping)。路由器 WAN 接口上的 Tcpdump 显示 Wireguard 数据包正在到达路由器。但路由器 wg0 上的 Tcpdump 显示它没有收到任何数据包。

我很确定问题是 Wireguard 正在默默地丢弃源 IP 未在(路由器上)AllowedIPs 中配置的数据包。但问题是我无法将 0.0.0.0/0 放在路由器 wg0.conf 上,因为它将开始使用隧道作为整个网络的默认网关!

使用 Wireguard 作为非默认网关是否无法进行基于源的路由?使用其他隧道软件是否有任何潜在的解决方法?我真的很喜欢 Wireguard 的速度,但如果没有 SNAT/Masquerade,它就会变得极其有限。

更新: 刚刚找到这篇文章: https://techoverflow.net/2021/07/09/what-does-wireguard-allowedips-actually-do/ 它解释说,wireguards“防火墙”和路由使用AllowedIPs捆绑在一起。

再进行一点测试,我可以简单地将路由器上的 AllowedIPs 设置为 0.0.0.0/0,并在 wg0.conf 中添加一条 postup 规则以删除默认网关路由,而只添加一条到隧道 IP 的静态路由。 (不幸的是,wireguard 选择将“防火墙”和路由合并为一个选项)

路由器 wg0 接口上的 Tcpdump 显示数据包现在正在穿过隧道。路由器LAN接口上的Tcpdump显示数据包已发送出去,并且Web服务器正在响应。但现在的问题是,那些基于接口源的路由规则似乎不起作用,因为 Web 服务器响应没有传递到wireguard 隧道中。

路由器 WAN 接口上的 Tcpdump 显示 Web 服务器 syn-ack 被推出该网关。所以现在我的问题出在我上面提到的基于源的路由规则上。基于源的路由超出了我的知识范围,因此非常感谢任何有关这些的帮助。

答案1

你已经成功了 90%。vpsrt在路由器上设置自定义路由表时:

echo 200 vpsrt >> /etc/iproute2/rt_tables

ip rule add from 192.168.200.2 table vpsrt prio 1
ip route add default via 192.168.200.1 dev wg0 table vpsrt

您应该使用网络服务器的IP 地址,而不是路由器的IP 地址,第二行:

ip rule add from 192.168.0.2 table vpsrt prio 1

这将指示您的路由器将所有流量从您的 Web 服务器发送到 WireGuard 隧道。只要您将其AllowedIPs=0.0.0.0/0作为路由器 WireGuard 配置中 VPS 服务器对等条目的一部分,WireGuard 隧道就会接受该流量,并将其发送回 VPS 服务器。

此外,如果您在路由器的 WireGuard 配置中指定该表,则不需要上面的第三行:

[Interface]
Address=192.168.200.2/32
PrivateKey=*
Table=vpsrt

[Peer]
Endpoint=PUBIPVPS:50000
PublicKey=*
AllowedIPs=0.0.0.0/0

通过该设置,wg-quick会将默认路由添加到您的自定义vpsrt表中,而不是扰乱全局默认路由。

另外,如果你不想路由全部从 Web 服务器到 VPS 的流量 - 仅来自 TCP 端口 80 和 443 的响应 - 您可以使用这些规则代替上面的第二行:

ip rule add from 192.168.0.2 ipproto tcp sport 80 table vpsrt priority 1
ip rule add from 192.168.0.2 ipproto tcp sport 443 table vpsrt priority 2

答案2

您可以考虑使用 VRF(虚拟路由和转发)。 VRF 用于配置具有自己的默认网关的单独路由表。您可以将您的wireguard 接口和Web 服务器连接到VRF,并且流量将与当前现有的连接分开。

这是使用 VRF 的一个很好的例子:https://interpip.es/linux/creating-a-vrf-and-running-services-inside-it-on-linux/

相关内容