我想新增一條規則,丟棄IPv4
帶有任何IP option
跟隨標頭的資料包。據我了解,IHL
標頭中的(Internet 標頭長度)欄位包含 IPv4 標頭中 32 位元字的數量,包括選項。所以,我的理解是,規則應該從IHL
字段中獲取資料包+選項長度並與20(不含選項的IPv4標頭長度)進行比較,如果大於20,則丟棄資料包。
是否有一個特定的iptables
模組允許檢查IP
標頭並評估(進行算術運算)?
答案1
iptables
包括u32
match 方法,該方法允許對資料包負載執行一些按位(但不是任意算術)操作、範圍比較和一些類似指標的間接尋址以匹配條件:
U32測試從資料包中提取的最多4個位元組的數量是否具有指定值。提取內容的規範足夠通用,可以從 tcp 標頭或有效負載中找到給定偏移量處的資料。
它有自己的子語言語法,應該檢查手冊中的語法和範例。
國際人道法是IP 標頭大小(以32 位元區塊而不是位元組為單位),並且是標頭中前32 位的一部分(對於IPv4 值為0x04 的版本,為4 位,後面跟著IHL 的4 位)並且,因此如果沒有選項,此大小應為最小大小:20(位元組)/4(每 32 位元字的位元組數),因此 IHL = 5(32 位元字)。我不會處理 IHL < 5 的無效情況,IPv4 堆疊應該已經解決了這個問題。
這翻譯成:
- 取前 32 位元值
- 掩蓋國際人道法部分
- 將其移位 24 位元
- 將相等性與 5 進行比較(將結果與
!
匹配項相反)
因此要丟棄這樣的傳入資料包iptables:
iptables -A INPUT -m u32 ! --u32 '0 & 0x0F000000 >> 24 = 5' -j DROP
沒有反轉(而是匹配 6 或更大):
iptables -A INPUT -m u32 --u32 '0 & 0x0F000000 >> 24 = 6:0xF' -j DROP
手冊有一個類似的範例,其中移位 24 位元,然後乘以 4(因此僅移位 22 位元)以獲得位元組而不是 32 位元字(因為u32
稍後使用的指標使用 8 位元位址),以檢索第4 層有效負載並繼續進一步操作:
... 0 >> 22 & 0x3C @ 0 >> 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 >> 22 & 0x3C = 20' -j DROP
沒有反轉(並且不關心第一個下一個可能值不是 21 而是 24 也不關心確切的最大值,只要給定的值更大):
iptables -A INPUT -m u32 --u32 '0 >> 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 之間的值表示不正常。
給予:
iptables -A INPUT -m u32 ! --u32 '0 = 0x45000000:0x45FFFFFF' -j DROP
或者:
iptables -A INPUT -m u32 --u32 '0 = 0x46000000:0x4FFFFFFF' -j DROP
選擇你的選擇。