我在 Linux (Ubuntu 18.04) 上制作了一个 C 程序,通过 IPIP 将流量转发到另一台服务器。当 IPIP 端点发回回复时,程序也会在剥离外层 IP 标头后将数据发回给客户端。机器流量上的应用程序和 IPIP 隧道端点被转发到位于网络命名空间内,IPIP 隧道是默认路由。这一切都很好。但是,我想实现一些东西,以便应用程序通过POSTROUTING
IPTables 中的链将源 IP 地址欺骗到转发机器 IP 来直接将流量发送回客户端。这将减少转发机器上的负载,因为应用程序不需要通过 IPIP 隧道将流量发送回客户端,我相信它会使其更加一致。
为此,我尝试设置一个 veth 对,其中一个 veth 在默认网络命名空间中,而对等 veth 在应用程序的自定义网络命名空间中。我还在主网络命名空间上设置了一个网桥,为其分配了一个 IP 地址,并在POSTROUTING
链中创建了一个 SNAT 规则,以将流量作为特定 IP 输出。然后,我在主网络命名空间上桥接了 veth 接口。应用程序仍然绑定到 IPIP 隧道,但是当它需要发送出站流量时,它会通过默认路由发送流量。因此,我将默认路由设置为网络命名空间内的 veth 接口。
所有这些大部分都在起作用。来自应用程序的流量直接发送回客户端,客户端响应转发服务器。然后将流量发送回服务器,流量通过 IPIP 转发到。我通过tcpdump
. 但是,我正在运行的应用程序没有处理回复。我相信这样做的原因是应用程序期望响应返回到veth
接口(默认路由),因为这就是它用来将回复发送回客户端的方式。不幸的是,该应用程序是闭源的,所以我无法检查代码。但是,我可能会创建一个测试 C 程序,该程序使用默认路由发送出站连接并进行进一步的故障排除。
我只是想知道是否有人对此有建议。我已经阅读了一些关于通过 IPTables 标记数据包的内容。我不完全确定在客户端回复并将其发送到转发服务器后该标记是否会保留。
我相信在 IPIP 隧道上会出现某些流量,然后在默认路由上会出现其他流量。在我的例子中,连接到应用程序的客户端正在向 IPIP 隧道发送流量,而 IPIP 隧道正在等待它。但是,该应用程序还与骨干网建立出站连接,我相信这是网络命名空间内默认接口上预期的流量类型。
在默认路由上预期所有流量的情况下,是否可以将流量从转发服务器转发到此特定接口,同时删除 IPIP 协议(剥离外部 IP 标头等)?我认为这需要在流量到达 IPIP 隧道后发生。
话虽如此,我想使用 IPIP 的原因是因为我可以在目标机器上执行 NAT(使用内部 IP 标头的目标地址将流量转发到 IPIP 隧道)。因此,我宁愿不要摆脱 IPIP 隧道。
非常感谢任何帮助,如果您需要更多信息,请告诉我!
我只是想提供一个更新。在发布这个问题大约一周后,我通过创建一个自动将出站 IPIP 数据包直接发送回客户端的 TC BPF 程序解决了这个问题。对于那些感兴趣的人,请随时在这里查看。
谢谢!