不要删除本地 IP 地址 1.1.1.6。您正在创建路由问题,而纠正这些路由问题不是netfilter的职责。即使您添加了防止这些循环的防火墙规则,使用不正确的路由也不是明智的行为。
同样,您可以选择删除 SNAT 规则的源 IP 选择器,但最好不要选择没有接口:(即,如果您选择此规则:)iptables -t nat -A POSTROUTING -j SNAT --to-source 1.1.1.6。它之所以有效,是因为有私有 IP 地址,在 Internet 上不可路由。如果不是这种情况,任何来自外部试图到达linux-router的 eth2 接口后面的 LAN 的连接都将被 SNAT 到 1.1.1.6。
例如,如果您添加了 DNAT 规则以使来自linux-srv的某些服务可从 Internet 访问,也会出现这种情况,从而防止linux-srv看到与 1.1.1.6 不同的源地址。这是模拟中的一个具体示例(将 1.1.1.6 恢复到linux-router):
netfilter与路由无关。这是解释下面发生的事情的重要内容。netfilter的 NAT 处理会改变地址,并且在某些情况下,当这在路由决策之前完成时,这反过来会改变路由决策。netfilter本身不做路由决策:这只是路由堆栈的作用。
我在下面假设linux-router没有额外的防火墙规则(在默认的iptables 过滤表中),因为它从未在问题中提及。另外,为了避免增加案例来解决,我假设在 10.99.99.0/24 LAN 中除了linux-srv(和linux-router)之外没有其他系统需要考虑(解决它们也不难)。
关于删除 1.1.1.6
SNAT 发生在 POSTROUTING,在任何路由决定之后。如果 SNAT 看到与给定条件匹配的 IP,它将添加一个 conntrack 条目来处理回复。在linux-router上会发生类似的事情(使用
conntrack -E -e NEW
):确保回复真的会回来不是netfilter的工作。这又是路由堆栈作业(包括linux-router无法控制的外部路由)。
在被删除之前,1.1.1.6 是linux-router的 IP 。添加此 IP 的接口并不重要,因为 Linux 遵循弱主机模型:它可以回答在任何接口上收到的对该 IP 的查询。删除此条目不会阻止接收 1.1.1.6 的数据包,因为M10i具有到达 1.1.1.6 的特定路由:使用 1.1.215.48 属于linux-router。所以linux-router永远不会收到此 IP 的 ARP 请求:来自M10i的 ARP 请求始终是 1.1.215.48(同样,M10i的 ARP 表将只缓存 1.1.215.48,而不是 1.1.1.6)。这意味着这个 IP 的存在无关紧要:linux-router将始终接收 1.1.1.6 的流量。但现在有区别了:
如果数据包与来自linux-srv的先前活动无关,则此数据包将到达第一个路由决策,如图所示。根据其当前的路由表,这应该是这样的:
如果是M10i(或 1.1.215.32/27 LAN 中的任何系统),linux-router也会不时添加 ICMP 重定向,如下所示:
无论如何,对于来自互联网的数据包,数据包将被发送回M10i,这可能正在实施严格的反向路径转发:这个路由返回的数据包将被M10i丢弃,因为它的源(198.51.100.101)位于错误的一侧它的路由表,因此被严格路径转发过滤。如果没有严格的反向路径转发,这将导致M10i和linux-router之间出现循环,直到数据包的 TTL 减为 0,然后数据包也被丢弃。
上一个示例:从 8.8.8.8 tcp 端口 80 到 1.1.1.6 端口 57490 收到的回复数据包,将被跟踪
conntrack -E
:在某个预路由点,conntrack将处理“de-SNAT”(提醒一下,这个数据包甚至不会再次遍历iptables的 nat 表,这也写在前面的示意图中:“nat”表仅用于“NEW” “连接)。目标 IP 现在更改为 10.99.99.50,数据包到达第一个路由决策:它被路由到linux-srv。一切正常。
所以我解释了当你删除 1.1.1.6 时会发生什么:不会影响linux-srv作为互联网客户端,但会在M10i和linux-router之间为无关的入口数据包造成一些轻微的中断。
如果您希望 Internet 上的某些客户端使用linux-router上的 DNAT 规则访问linux-srv,那么对于受影响的连接(例如:linux-srv tcp 端口 80 上的 Web 服务器),一切都会正常工作而不会中断。对于其他尝试, M10i和linux-router之间再次存在小问题。
关于将源 IP 选择器/过滤器删除到 SNAT 规则
未提供信息:传出接口上是否还有选择器/过滤器。下面的两条规则将从
iptables -t nat -n -L
(但不是 fromiptables -t nat -n -v -L
或 betteriptables-save
)获得相同的输出:或者
实际上,在这种情况下,如果您现在使用以下两个命令中的任何一个,都无关紧要:
因为从 eth0 一侧看不到私有 IP 目标地址,所以linux-router只能有效地路由一个IP 地址:linux-srv的 10.99.99.50 并且该路由只能在它首先从 10.99.99.50 启动时发生, 以便它被 SNATed 到公共 IP。由于iptables只会在初始连接(状态 NEW)时创建新的 conntrack 条目,因此在此之后 conntrack 条目将不再更改,一切都会正常工作。
从linux-router中删除 1.1.1.6
对于linux-srv,当它连接到 Internet 时,一切仍将按预期工作:前面的解释也适用。
对于从外部到 1.1.1.6 的任何未知传入连接(例如,从 198.51.100.101):
路由堆栈确定 1.1.1.6 应该路由到M10i(参见前面的解释)。在状态 NEW 中添加了一个暂定的 conntrack 条目,并且数据包到达 nat/POSTROUTING:数据包被 SNAT 到 1.1.1.6 并发送回M10i。M10i有一条到 1.1.1.6 的路由,并再次将更改后的数据包发送到linux-router,源 IP 和目标 IP 均为 1.1.1.6(因为源位于其路由表的正确一侧,它甚至不会被严格反向路径转发丢弃)。linux-router接收到一个数据包......从那里我无法判断它是否是一个错误,但这是在重现你的案例的实验中捕获的内容
conntrack -E
,从 198.51.100.101 接收到一个 TCP SYN 数据包:即使 netfilter 的行为不正常,M10i和linux-router之间也确实存在循环(直到 TTL 降至 0)。
结论
不要删除本地 IP 地址 1.1.1.6。您正在创建路由问题,而纠正这些路由问题不是netfilter的职责。即使您添加了防止这些循环的防火墙规则,使用不正确的路由也不是明智的行为。
同样,您可以选择删除 SNAT 规则的源 IP 选择器,但最好不要选择没有接口:(即,如果您选择此规则:)
iptables -t nat -A POSTROUTING -j SNAT --to-source 1.1.1.6
。它之所以有效,是因为有私有 IP 地址,在 Internet 上不可路由。如果不是这种情况,任何来自外部试图到达linux-router的 eth2 接口后面的 LAN 的连接都将被 SNAT 到 1.1.1.6。例如,如果您添加了 DNAT 规则以使来自linux-srv的某些服务可从 Internet 访问,也会出现这种情况,从而防止linux-srv看到与 1.1.1.6 不同的源地址。这是模拟中的一个具体示例(将 1.1.1.6 恢复到linux-router):
虽然可能不清楚,但这意味着预期的回复是从 10.99.99.50 到 1.1.1.6(而不是 198.51.100.101):linux-srv对真正连接到它的 IP 地址保持盲目,它总是会看到 1.1.1.6 .