Nftables

nftables中的數據包處理順序

  • January 25, 2022

我正在從 iptables 轉移到 nftables。我有一個關於 nftables 中數據包處理順序的基本問題。

由於可以創建多個相同類型的表,比如inet,並且可以在每個表中創建具有不同或相同優先級的鏈,處理順序是什麼。

例如,如果我創建以下內容,那麼順序是什麼。

table inet t1 {
   chain INPUT {
       type filter hook input priority 20; policy accept;
       ...
   }
}


table inet t2 {
   chain INPUT {
       type filter hook input priority 20; policy accept;
       ...
   }
}

雖然我知道鏈連接到不同的輸入,但我還沒有理解擁有不同表的邏輯。

道歉如果是一個愚蠢或基本的問題

範例中的排序將是undefined,但將遍歷兩個鏈(除非例如數據包在看到的第一個鏈中被丟棄)。

Netfilter 和網路/路由堆棧提供排序

這是Netfilter 和通用網路示意圖中的數據包流:

Netfilter 和通用網路中的數據包流

雖然它是在考慮iptables的情況下製作的,但當應用於nftables時,整體行為是相同的,但有細微差別(例如: manglefilter之間沒有分離,它都是nftables中的**過濾器,除了 mangle/OUTPUT 可能應該被翻譯成類型 route hook output ,或者在下部看到的ebtablesiptables之間的大部分橋混合更新:不存在與~~nftables~~存在但應該通過直接在橋系列中使用**nftables來避免 直接,如果那裡需要conntrack功能,則使用 kernel >= 5.3 (並且根本不使用核心模組br_netfilter)。

表的作用

nftables中的表不等同於iptables中的表:它不那麼嚴格。在nftables中,是一個容器,用於組織鏈、集合和其他類型的對象,並限制它們的範圍。與iptables相反,在同一個表中混合不同的鏈類型(例如:nat、filter、route)是完全可以接受的,有時還需要:例如,這是他們可以訪問公共的唯一方法,因為它的範圍僅限於表而不是全域(就像是iptables的伴侶ipset)。

然後,為了特定的處理或處理特定的流量,擁有同一系列的多個表也是完全可以接受的:在更改此表的內容時,不存在更改其他表中的規則的風險(儘管有仍然存在總體結果產生衝突影響的風險)。它有助於管理規則。例如,nftlb負載平衡器創建的表(在各個系列中)都命名為nftlb,旨在僅由其自身管理,而不與其他使用者定義的表發生衝突。

鉤子之間和鉤子內的排序

在給定的系列(netdev、bridge、arp、ip、ip6)中,註冊到不同鉤子(入口、預路由、輸入、轉發、輸出、後路由)的鏈按照 Netfilter 提供的鉤子順序進行排序,如上圖所示。優先級的範圍僅限於同一個鉤子,在這裡無關緊要。例如在轉發數據包的情況下type filter hook prerouting priority 500仍然發生。type filter hook forward priority -500

在適用的情況下,對於給定家族的每個可能的鉤子,每個鏈都將與在同一地點註冊的其他鏈競爭。除了定義族之外,這些在這裡沒有任何作用。只要優先級不同,在給定的鉤子類型內,數據包將從最低優先級到最高優先級遍歷該鉤子內的鏈。如果完全相同的優先級用於相同系列和鉤子類型的兩個鏈,則順序變為未定義。在創建鏈時,目前核心版本是在對應的鍊錶結構中優先級相同的鏈之前還是之後添加鏈?下一個核心版本是否仍會保持相同的行為,或者一些優化會改變這個順序?它沒有記錄。兩個鉤子仍然會被呼叫,但它們被呼叫的順序是未定義的。

這怎麼可能?這是下面手冊頁的引用,只是為了澄清一個數據包可以在同一個鉤子中多次接受(或不接受):

accept

終止規則集評估並接受數據包。數據包仍然可以稍後被另一個鉤子丟棄,例如前向鉤子中的接受仍然允許稍後在後路由鉤子中丟棄數據包,或者另一個具有更高優先級的前向基鏈,然後在處理管道中進行評估。

例如,如果一個連結受某個數據包,而另一個鏈丟棄了這個相同的數據包,則總體結果將始終是drop。但是一個鉤子可能做了額外的動作,導致了副作用:例如,它可能在一個集合中添加了數據包的源地址,而另一個名為 next 的鏈丟棄了數據包。如果順序顛倒,數據包首先被丟棄,這個“副作用”動作就不會發生,集合也不會被更新。所以在這種情況下應該避免使用完全相同的優先級。對於其他情況,主要是在沒有下降的情況下,這無關緊要。除非知道這無關緊要,否則應避免使用相同的優先級。

與其他網路子系統的關係

在一個鉤子中,所有整數範圍都可用於選擇順序,但一些特定的門檻值確實很重要。

nftables的 wiki中,以下是對ip系列有效的遺留**iptables掛鉤值,其中還包括其他子系統:

NF_IP_PRI_CONNTRACK_DEFRAG (-400): 碎片整理

NF_IP_PRI_RAW (-300)的優先級 : 原始表在連接跟踪操作之前放置的傳統優先級

NF_IP_PRI_SELINUX_FIRST (-225): SELinux 操作

NF_IP_PRI_CONNTRACK (-200): 連接跟踪操作

NF_IP_PRI_MANGLE (-150): mangle 操作

NF_IP_PRI_NAT_DST (-100): 目標 NAT

NF_IP_PRI_FILTER (0): 過濾操作, 過濾表

NF_IP_PRI_SECURITY (50): 可以設置 secmark 的安全表的位置 例如

NF_IP_PRI_NAT_SRC (100): 源NAT

NF_IP_PRI_SELINUX_LAST (225): SELinux at packet exit

NF_IP_PRI_CONNTRACK_HELPER (300): connection tracking at exit

其中只有少數真正重要:那些不是來自iptables的。例如(非詳盡)ip家庭:

  • NF_IP_PRI_CONNTRACK_DEFRAG (-400):為了讓一個鏈能夠看到傳入的 IPv4 片段,它應該以低於 -400 的優先級在*預路由中註冊。*在此之後,只能看到重新組裝的數據包(並且檢查片段是否存在的規則永遠不會匹配)。
  • NF_IP_PRI_CONNTRACK (-200):對於在conntracknat**之前 執行的鏈,它應該在預路由輸出中以低於 -200 的優先級註冊。例如,在優先級註冊(或任何其他值 < -200 但仍然 > -400,如果想要在所有情況下匹配埠)添加一條語句以防止conntrack為該數據包創建連接條目。因此,相當於iptables的 raw/PREROUTING 的**nftables只是過濾具有足夠優先級的預路由。NF_IP_PRI_RAW (-300)notrack

雜項

我忽略了其他家族和特殊情況:例如inet家族同時註冊在ipip6家族的鉤子中。或者當 NAT 規則匹配時可能表現不同的類型 nat(它可能不會再次遍歷同一個鉤子的其他nat鏈,我不完全確定,它可能取決於核心版本)並且確實依賴於conntrack(例如:優先級為 -200 的預路由)並且至少因為核心 4.18 僅與其他nat類型的鏈競爭,而不是與其他類型的鏈競爭(對於**類型過濾器鏈,它將始終以優先級 -200 看到)。

當還使用iptables-legacy(或iptables-nft)時,所有這些仍然適用,並且優先級選擇很重要。來自iptables-legacynftables的 NAT 規則不應與小於 4.18 的核心混合,否則可能會發生未定義的行為(例如:一個鏈將處理所有 NAT,另一個將無法處理,但第一個子系統要註冊,而不是最低優先級的鏈獲勝)。

引用自:https://unix.stackexchange.com/questions/607358