NAT 數據包在錯誤的網關上發出
我有兩個介面,比如說
eth0
和eth0.4000
vlan。兩者都有一個預設網關。當程序直接在介面上偵聽時,一切都按預期工作。但不適用於
hostPort
Kubernetes 的綁定。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 顯示 sourceIP 是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-Plugin埠映射創建的,該映射使用 DNAT 和 SNAT(連結詳細資訊)。所以網關查找發生在早期。當我手動添加從容器 IP 到查找表 1 的路由時,它使用 vlan 介面工作,但會破壞 eth0。
所以問題是 - 在NAT 用 interface-ip 替換 container-ip之後發生路由需要做什麼?
你是對的,來自 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 的有用安全網(例如,因為其他東西使用了特定標記)。