Linux

netfilter:丟棄具有 IP 選項的數據包

  • October 29, 2021

我想添加一個規則來丟棄一個IPv4帶有任何IP option跟隨頭的數據包。我了解標頭中IHL的(Internet 標頭長度)欄位包含 IPv4 標頭中的 32 位字數,包括選項。所以,我的理解是,規則應該從IHL欄位中獲取數據包+選項長度並與 20(不帶選項的 IPv4 標頭長度)進行比較,如果大於 20,則丟棄數據包。

是否有iptables允許檢查IP標頭和評估(進行算術運算)的特定模組?

iptables包括u32match 方法,它允許對數據包有效負載進行一些按位(但不是任意算術)操作、範圍比較和一些類似指針的間接操作以匹配條件:

u32

U32 測試從數據包中提取的最多 4 個字節的數量是否具有指定值。提取內容的規範足以從 tcp 標頭或有效負載中找到給定偏移量的數據。

它有自己的子語言語法,需要檢查手冊中的語法和範例。

IHL是 IP 標頭大小(以 32 位塊而不是字節為單位)並且是標頭中前 32 位的一部分(4 位用於版本,IPv4 值為 0x04,後跟 4 位用於 IHL),所以如果有沒有選項,這個大小應該是最小大小:20(字節)/4(每 32 位字的字節數)所以 IHL = 5(32 位字)。我不會處理 IHL < 5 的無效情況,IPv4 堆棧應該已經解決了這個問題。

這轉化為:

  • 取前 32 位值
  • 為國際人道法部分掩蓋它
  • 將其移動 24 位
  • 將相等性與 5 進行比較(!在匹配時反轉結果)

因此,要使用iptables丟棄此類傳入數據包:

iptables -A INPUT -m u32 ! --u32 '0 & 0x0F000000 &gt;&gt; 24 = 5' -j DROP

沒有反轉(匹配 6 或更大):

iptables -A INPUT -m u32 --u32 '0 & 0x0F000000 &gt;&gt; 24 = 6:0xF' -j DROP

手冊有一個類似的例子,它被移動了 24 位,然後乘以 4(所以只移動了 22 位)得到字節而不是 32 位字(因為u32稍後使用的指針使用 8 位地址),以檢索第 4 層有效載荷並繼續進行進一步操作:

... 0 &gt;&gt; 22 & 0x3C @ 0 &gt;&gt; 24 = 0"

第一個 0 表示讀取字節 0-3,>>22 表示向右移動 22 位。移動 24 位將給出第一個字節,因此只有 22 位是該字節的四倍加上更多位。&3C 然後消除右側的兩個額外位和第一個字節的前四位。例如,如果 IHL=5,那麼 IP 報頭是 20 (4 x 5) 字節長。

$$ … $$

給予 OP 的案例:

iptables -A INPUT -m u32 ! --u32 '0 &gt;&gt; 22 & 0x3C = 20' -j DROP

沒有反轉(並且不關心第一個可能的值不是 21 而是 24 也不關心確切的最大值,只要給定的值更大):

iptables -A INPUT -m u32 --u32 '0 &gt;&gt; 22 & 0x3C = 21:0xFF' -j DROP

第一種方法可以簡化為:

  • 取前 32 位值
  • 為國際人道法部分掩蓋它
  • 將相等性與 (5<<24) 進行比較,即與 0x05000000 進行比較(同上)

給予:

iptables -A INPUT -m u32 ! --u32 '0 & 0x0F000000 = 0x05000000' -j DROP

或者:

iptables -A INPUT -m u32 --u32 '0 & 0x0F000000 = 0x06000000:0x0F000000' -j DROP

甚至:

  • 取前 32 位值
  • 將值與 0x45000000 和 0x45FFFFFF 之間的範圍進行比較以表示 OK(IPv4始終以 4 開頭,並且 IHL 部分之後的任何值都將被忽略)或在 0x46000000 和 0x4FFFFFFF 之間的範圍內表示不OK。

給予:

iptables -A INPUT -m u32 ! --u32 '0 = 0x45000000:0x45FFFFFF' -j DROP

或者:

iptables -A INPUT -m u32 --u32 '0 = 0x46000000:0x4FFFFFFF' -j DROP

選擇您的選擇。

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