Linux

採用 DNAT 規則到本地 IP 的數據包消失

  • July 8, 2020

過去一周我一直在處理一個非常奇怪的問題,我想知道是否有人對繼續調試有任何建議。我們有一台帶有兩個乙太網介面的機器,其中一個用作我們的網際網路連接(比如說 IP A),另一個具有我們網路流量的子網(包括 IP A)通過我們的路由器鏡像到它;該介面具有 IP B。我們有一個應用程序,它從鏡像介面接收流量並對其進行過濾,將一些數據包轉儲到 tun 介面(讓我們簡化一下,這裡只說 tun0,儘管在實際應用程序中,我們為每個執行過濾的核心都有一個)。然後,我們嘗試將在 tun0 上接收到的數據包 DNAT 返回到埠C上的 IP B以便另一個應用程序可以攝取它們。

我們在 nat 表的 PREROUTING 鏈中設置了一個規則來執行 DNAT,如下:

iptables -t nat -I PREROUTING -p tcp -i tun0 -j DNAT --to <B>:<C>

我已經確認這條規則正在被擊中,無論是數據包跟踪還是從 iptables 中查看數據包號。然而,在那之後,數據包似乎消失了——我希望它們接下來進入 INPUT 鏈,因為 IP B是本地地址(我已經確認ip route get <B>是指lo),但是數據包不會進入 INPUTFORWARD 鏈,這讓我相信他們在路由決策中被丟棄了。我在網上看到的一切似乎都表明這是rp_filter,forwarding或的問題route_localnet,但是我已經確認了以下所有內容:

net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.tun0.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 0
net.ipv4.ip_forward = 1
net.ipv4.conf.tun0.forwarding = 1
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.all.route_localnet = 1
net.ipv4.conf.tun0.route_localnet = 1
net.ipv4.conf.lo.route_localnet = 1

當我打開火星日誌時,我看到以下內容:

IPv4: martian source <B> from <A>, on dev tun0

這似乎證實了 DNAT 正在產生一些影響,但考慮到rp_filter=0這讓我感到困惑。

在這一點上,我不知道如何繼續調試,因為數據包似乎在 DNAT 步驟後從地球表面消失了,而不是火星日誌,非常感謝一些指導!謝謝!

被饋送到我的鏡像介面的數據包來自我的本地機器,我不知道任何通過本地源 IP 地址進入 INPUT 鏈的數據包都會被丟棄。數據包傳輸到我們的路由器並返回到我們的另一個乙太網介面這一事實使得這一點變得不那麼明顯(例如,“如果這台機器都通過路由器,那麼這台機器與我們網路上的其他機器有什麼不同”),但相同源IP(邏輯上)仍然保留。這種行為對於“正常”案例是有意義的,儘管我無法在任何關於該主題的外部文件中找到它的描述(這可能是由於缺乏知識,但我可以保證這不是缺乏努力) ; 我只是在閱讀Linux Kernel 的原始碼時才發現它:

/*
*  NOTE. We drop all the packets that has local source
*  addresses, because every properly looped back packet
*  must have correct destination already attached by output routine.
*

因為我們將數據包直接轉儲到 tun 介面並保留原始源 IP 地址,這違背了核心對“正常”情況的預期,它默默地丟棄了數據包,使得追踪原因相當痛苦。看起來(從讀取同一文件的不同部分)這個火星日誌並不一定表明該數據包因此而被阻止- 只是它被檢測為火星。展望未來,我們的解決方案可能是“不要那樣做”(從同一台機器發出請求),或者想辦法在 INPUT 鏈執行之前重寫源 IP 地址,就像 POSTROUTING 中通常的 SNAT 步驟鏈就來不及了。

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