NAT 数据包通过错误的网关发出

NAT 数据包通过错误的网关发出

我有两个接口,假设为eth0eth0.4000VLAN。两者都有一个默认网关。当进程直接侦听接口时,一切都按预期工作。

但不适用于hostPortKubernetes 的绑定。

vlan.gw-mac > eth0-mac,    ethertype 802.1Q (0x8100), length 78: vlan 4000, p 0, ethertype IPv4 (0x0800), clientIP.38712 > vlanIP.80: Flags [S]
eth0-mac    > eth0.gw-mac, ethertype IPv4   (0x0800), length 74:                                          vlanIP.80      > clientIP.38712: Flags [S.]

SYN 来自vlan.gateway,被转发到容器,但答案 SYN-ACK 离开堆栈eth0.gw并且不正确,vlan.gw但 tcpdump 显示源 IP 是vlanIP

路由表看起来不错:

# ip route get to <clientIP> from <vlanIP> dev eth0.4000
<clientIP> from <vlanIP> via <vlan.gw> dev eth0.4000 table 1 uid 0

hostPort 映射通过以下方式创建:CNI 插件端口映射它使用 DNAT 和 SNAT(详细信息链接)。因此网关查找发生得太早了。当我手动将路由从容器 IP 添加到查找表 1 时,它可以使用 vlan 接口工作,但会破坏 eth0。

所以问题是 - 需要做什么才能实现路由NAT 将容器 IP 替换为接口 IP?

答案1

您说得对,DNAT 的隐式 SNAT 发生得太晚了:此时,路由决策已经做出,因此在错误的接口上使用正确的源 IP。

为了避免这种情况,您需要更深入地了解基于策略的路由。在https://superuser.com/questions/638044/source-based-policy-routing-nat-dnat-snat-aka-multi-wans-on-centos-5可以使用。

为此,您需要在 mangle 表的 PREROUTING 链中包含以下内容:

-A PREROUTING -i vlanIface -m state --state NEW,RELATED,ESTABLISHED -d <vlanIP> -j CONNMARK --set-mark 0x10/0x10
-A PREROUTING -m connmark --mark 0x10/0x10 -j CONNMARK --restore-mark --cfmask 0x10

这样,所有属于通过 vlanIface 发起的连接数据包的 fwmark 中都会设置 0x10。然后可以将其用于 PBR。假设您的 pod 网络是 10.0.0.0/8,辅助网关的表是 1:

ip rule add fwmark 0x10/0x10 from 10.0.0.0/8 table 1

您也许可以省略from 10.0.0.0/8,但它是防止错误设置 fwmarks 的有用安全网(例如,由于其他东西使用了特定标记)。

相关内容