Iptables

在 Azure K8S 中執行的容器上的 iptables 中使用 fwmark

  • August 30, 2021

我有一個奇怪的案例,在 Azure Kubernetes 中執行的 pod 需要通過專用 VPN 隧道將流量從特定埠路由到特定目標。但是這些目標是私有 IP,因此可以為不同的目標使用相同的 IP。除了路由之外的 pod 也是目標連接的 OpenVPN 伺服器。一個例子:

到達埠 10 的通信通過 VPN IP 10.118.0.2 路由到 IP 10.0.0.4:80

同時我們可以擁有:

到達埠 20 的通信通過 VPN IP 10.118.0.3 路由到 IP 10.0.0.4:80

儘管目標 IP 相同,但它們是不同的機器。所以為了實現這一點,我想出了這個可能的解決方案:

/sbin/iptables --table mangle --insert PREROUTING --destination "192.168.0.100" -i eth0 -p tcp --dport "10" --jump MARK --set-mark "10"
/sbin/iptables --table nat --insert PREROUTING --destination "192.168.0.100" -i eth0 -p tcp --dport "10" --jump DNAT --to-destination "10.0.0.4:80"
/sbin/ip rule add prio "10" from all fwmark "10" lookup "10"
/sbin/ip route add "10.0.0.4" via "10.118.0.2" table 10

這將允許兩個通信同時工作,並將流量路由到正確的機器。但我看到的是數據包在 mangle 表中被標記。但是永遠不會到達 NAT 表。我發現它與rt_filter有關。更多關於下面的內容。就像現在一樣,它正在工作,是這樣的:

/sbin/iptables --table nat --insert PREROUTING --destination "192.168.0.100" -i eth0 -p tcp --dport "10" --jump DNAT --to-destination "10.0.0.4:80"
/sbin/ip route add "10.0.0.4" via "10.118.0.2"

但是,如果建立了第二條路由,就像在第一個範例中一樣,命令將如下所示:

/sbin/iptables --table nat --insert PREROUTING --destination "192.168.0.100" -i eth0 -p tcp --dport "20" --jump DNAT --to-destination "10.0.0.4:80"
/sbin/ip route add "10.0.0.4" via "10.118.0.3"

這將在主路由表中為同一目標創建另一條路由。但是,當訪問 192.168.0.100 時,使用者可能會被路由到與 10.118.0.3 或 10.118.0.2 連接的機器。

除了這些規則之外,對於所有這些規則,始終啟用該規則以允許流量返回到與 10.118.0.X 通信的 tap0 介面:

iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE

不幸的是我不知道使用者源IP,否則很容易解決。到達此埠的任何通信的源 IP 將始終相同,因為通信需要通過另一個服務來掩蓋真實的源 IP。

我在其他主題中看到,為了標記容器/pod 中的傳入數據包,我需要禁用 rt_filter。但是我不能這樣做,它說它是一個只讀文件系統,我不知道是否可以在 Azure Kubernetes 集群中更改它。

除了標記數據包,還有其他解決方案嗎?還是有關數據包標記的其他內容?

所以我終於找到了解決方案。問題在於 PREROUTING 中的數據包損壞。在 POSTROUTING 中處理數據包(因此,在 eth0 的出口處),它們能夠從 tap0 返回到 eth0,然後返回到客戶端。最終結果如下所示:

/sbin/iptables --table mangle --insert POSTROUTING --destination "192.168.0.100" -o eth0 -p tcp --dport "10" --jump MARK --set-mark "10"
/sbin/iptables --table nat --insert PREROUTING --destination "192.168.0.100" -i eth0 -p tcp --dport "10" --jump DNAT --to-destination "10.0.0.4:80"
/sbin/ip rule add prio "10" from all fwmark "10" lookup "10"
/sbin/ip route add "10.0.0.4" via "10.118.0.2" table 10

引用自:https://serverfault.com/questions/1075810