采用 DNAT 规则到本地 IP 的数据包消失

采用 DNAT 规则到本地 IP 的数据包消失

大约过去一周,我一直在处理一个相当奇怪的问题,我想知道是否有人对继续调试有什么建议。我们有一台带有两个以太网接口的机器,其中一个用作我们的互联网连接(假设 IPA),另一个包含我们网络流量的子网(包括 IPA)通过我们的路由器镜像到它;该接口有 IP。我们有一个应用程序,它从镜像接口接收流量并对其进行过滤,将一些数据包转储到 tun 接口(我们简化一下,这里只说 tun0,但在实际应用中,我们为每个执行过滤的核心都有一个)。然后,我们尝试将 tun0 上收到的数据包 DNAT 回 IP在港口C以便其他应用程序可以吸收它们。

我们在nat表的PREROUTING链中设置了一条规则来执行DNAT,如下所示:

iptables -t nat -I PREROUTING -p tcp -i tun0 -j DNAT --to <B>:<C>

我已经确认该规则被命中,既有数据包跟踪,也有从 iptables 查看数据包编号。然而,此后,数据包似乎消失了——我预计它们接下来会以 IP 的形式进入 INPUT 链是一个本地地址(我已确认ip route get <B>指的是lo),但是数据包没有进入 INPUT或者FORWARD 链,这让我相信它们在路由决策中被丢弃了。我在网上看到的所有内容似乎都表明这是或 的问题rp_filter,但是我已经确认了以下所有内容:forwardingroute_localnet

net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.tun0.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 0
net.ipv4.ip_forward = 1
net.ipv4.conf.tun0.forwarding = 1
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.all.route_localnet = 1
net.ipv4.conf.tun0.route_localnet = 1
net.ipv4.conf.lo.route_localnet = 1

当我打开火星日志记录时,我看到以下内容:

IPv4: martian source <B> from <A>, on dev tun0

这似乎证实了 DNAT 确实一些效果,但鉴于rp_filter=0此,我感到困惑。

此时,我不知道该如何继续调试,因为除了火星日志之外,DNAT 步骤之后的数据包似乎从地球表面消失了,非常感谢您的指导!谢谢!

答案1

被馈送到我的镜像接口的数据包来自我的本地计算机,我不知道任何进入 INPUT 链的具有本地源 IP 地址的数据包都会被丢弃。数据包传输到我们的路由器并返回到我们的其他以太网接口这一事实使这一点不那么明显(例如“如果它们都通过路由器,这台机器与我们网络上的其他机器有什么不同”),但相同的源 IP 仍然保留(逻辑上)。这种行为对于“正常”用例来说是有意义的,尽管我无法在任何有关该主题的外部文档中找到它的描述(可能是由于缺乏知识,但我可以保证这不是缺乏努力);我只是在阅读Linux 内核源代码

/*
 *  NOTE. We drop all the packets that has local source
 *  addresses, because every properly looped back packet
 *  must have correct destination already attached by output routine.
 *

因为我们将数据包直接转储到 tun 接口并保留原始源 IP 地址,这违背了内核对“正常”情况的预期,并且它默默丢包,追踪原因非常麻烦。此外(从阅读同一文件的不同部分来看)这个火星日志并不一定表明数据包受阻因为这个原因——只是检测到作为火星人。展望未来,我们的解决方案可能是“不要这样做”(从同一台机器发出请求),或者找出在 INPUT 链执行之前重写源 IP 地址的方法,因为 POSTROUTING 链中的常规 SNAT 步骤为时已晚。

相关内容