我有一个路由器使用 iptables 执行简单的 NAT 转换 iptables -t nat -o -j MASQUERADE
除了某些 TCP RST 和 FIN 数据包离开路由器未进行 NAT 的特殊情况外,该方法几乎所有情况下都能正常工作。
在这种情况下,我设置了 1 或 2 台客户端计算机来流式传输 Flash 视频(例如 www.nasa.gov/ntv)。在路由器上,我随后拆除并重新建立公共接口(即调制解调器)。正如预期的那样,Flash 流停滞。重新建立连接后,我尝试刷新 Flash 页面,我看到一些 TCP RST 和 [FIN,ACK] 数据包离开公共接口(我假设 Flash 尝试恢复其流)。
我不知道这些数据包如何能让路由器不进行 NAT
答案1
谢谢你的提示。我正是我需要的,它能让我走上正确的道路。
根本原因是局域网和公共接口之间未过滤的转发。当公共接口被拆除时,它会清除 conntrack 条目。然后客户端尝试恢复其连接,并最终发出 RST 和 FIN 数据包。由于 NAT 仅在新连接上设置,因此这些数据包不会对路由器进行修改。
我必须更改我的转发规则,以仅允许 NEW、ESTABLISHED、RELATED 数据包从私有局域网转发。
答案2
放下[RST,确认]和[结束,确认]不起作用。有许多应用程序(如 ftp upload)无法确认 FTP 传输的完成。gscott 的评论是正确的方法,但还需要一个额外的要求。您必须通过应用策略使其变得严格
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -P INPUT DROP
为此,您需要指定所有规则,否则数据包将被丢弃。
答案3
这可能是 iptables 的 MASQUERADE 目标中的一个错误。在您的场景中,似乎有以下同时发生的事件:
- 这些数据包恰好属于状态表中已存在的连接
- 状态条目包含不再属于系统的 NAT 地址源
因此,伪装数据包的尝试可能会由于伪装的地址无效而失败,因此数据包将被不加改变地路由出去。
MASQUERADE 目标的预期行为是当接口关闭或地址更改时清除相应的状态条目,因此这种情况不应该发生。但是iptables 中存在一个古老的错误这听起来可能会引发类似的行为。
要进行进一步的故障排除,请记下路由器的公共 IP 地址,重现问题并使用(其中 12.34.56.78 是您之前记下的 IP 地址)查看状态表egrep 12.34.56.78 /proc/net/ip_conntrack
。如果尽管公共接口地址已更改,但您仍收到带有旧 IP 地址的 conntrack 行,则您可能遇到了 iptables 错误 - 考虑更新您的内核/iptables 并将问题报告给 netfilter 团队。
答案4
中的规则-t nat
仅适用于流(状态NEW
)中的第一个数据包。该流中的其他数据包将进行相同的处理,而无需对它们应用任何其他 iptables 规则。但无法启动流(例如FIN
和RST
,或者可能是 以外的任何数据包SYN
)并且与当前流无关的数据包将被 忽略-t nat
。iptables 状态机将这些数据包归类为 状态INVALID
。可以使用以下方法将它们过滤掉:
iptables -A FORWARD -m state --state INVALID -j DROP
根据您的其他规则,可能需要将此规则插入到-j ACCEPT
规则之前。