我正在尝试理解 physdev iptables 模块,但在使用 nat 表时遇到了问题,尤其是 POSTROUTING 链。因此,我的目标是使用 physdev 模块对桥接接口上的传出流量进行 SNAT。
这是我的迷你网络设置:PC1 - (enp6s0f0)BRIDGE(enp6s0f1) - PC2。PC1是 192.168.100.1/24,PC2 是 192.168.100.2/24。
我的桥梁设置是:
ifconfig enp6s0f0 down
ifconfig enp6s0f1 down
brctl addbr br0
brctl addif enp6s0f0 br0
brctl addif enp6s0f1 br0
ifconfig enp6s0f0 0.0.0.0 up
ifconfig enp6s0f1 0.0.0.0 up
ifconfig br0 169.254.100.1/32 up
该桥接设置工作正常,PC1 和 PC2 可以相互通信,但不能按预期与桥接器通信。
现在,例如,我想要以这样的方式设置 PC 和 BRIDGE 之间的通信,即 PC1 将 BRIDGE 视为 192.168.100.100,而 PC2 将 BRIDGE 视为 192.168.100.200。
所以我添加了路线:
route add -net 192.168.100.0/24 dev br0
现在,如果我从 BRIDGE ping 任何一台 PC,我就可以像预期的那样看到来自网桥的源 IP 为 169.254.100.1 的传出流量。
现在一切都与 iptables 有关。我的规则:
iptables -t nat -A POSTROUTING -s 169.254.100.1 -m physdev --physdev-out enp6s0f0 -j SNAT --to-source 192.168.100.100
iptables -t nat -A POSTROUTING -s 169.254.100.1 -m physdev --physdev-out enp6s0f1 -j SNAT --to-source 192.168.100.200
在此之后,我希望从网桥传出的所有流量都根据 physdev-out 进行 SNAT 到 192.168.100.100 或 192.168.100.200,但这并没有发生。为什么?我不知道。发生的事情是规则被忽略了。iptables -t nat -vnL 显示0 个数据包与规则匹配,tcpdump -i enp6s0f0 -p arp -n 显示所有 arp 请求都具有旧的 169.254.100.1 源 ip 地址。
还需要注意的是,我已经加载了br-netfilter模块,并且将bridge-nf-call-iptables设置为 1。
我使用的操作系统是 Ubuntu 20.04,但我也尝试了其他操作系统。我也在互联网上查找了信息,我知道还有其他几种方法可以实现我想要的行为,但我想弄清楚为什么这种特定方法不起作用。
我还查看了https://ebtables.netfilter.org/br_fw_ia/br_fw_ia.html,读完之后,我觉得一切都应该可以正常工作。请帮帮我
据我所知,
--physdev-out
只能用于匹配“桥接”流量,即来自另一台主机并通过桥接端口进入桥接的流量。来自“桥接主机”本身的流量以及来自另一台主机但正在 L3 转发的流量(即从某个接口进入“桥接主机”并通过桥接接口离开的流量)不被视为“桥接流量”。(在我看来,这是某种技术限制或设计缺陷,而不是错误。您可以在手册页INPUT
中看到提到了链,--physdev-in
而OUTPUT
没有提到链--physdev-out
。)我不确定你在这里到底想做什么,因为通常情况下,在一个主机上为它连接到的同一网络设置不同的地址几乎没有意义,尤其是当你使用一个 IP 子网并试图利用源 NAT 来实现你的目标时。然而,为了实现你显然想要的,我能想到的最好/唯一的方法是利用 netns 和 veth 对。(每个 netns 都被视为网络方面的主机。)
我不完全确定将物理以太网接口移动到新的 netns 是否总是可行的,但假设它是可行的,您可以创建一个 netns 并在其中创建网桥,然后将要用作网桥端口/从属端口的以太网接口移动到 netns 并在那里设置它们的主端口。最后创建一个 veth“对”,并将“对”的一端(例如
peer
)移动到 netns 并将其也从属到网桥。不要在网桥上配置 IP 地址和路由,而是在“默认”netns 中的 veth“对”的“端”(即不是网桥从属端口/端口的“端”)上配置它们。显然,应该将 SNAT 规则添加到网桥所在的 netns 的 iptables 中。
另请参阅
ip-link(8)
和ip-netns(8)
。