Netfilter是Linux2.4內核實現數據包過濾、數據包處理、NAT等的功能框架。該文討論了linux 2.4內核的netfilter功能框架,還對基於netfilter框架上的包過濾,NAT和數據包處理(packet mangling)進行了討論。閱讀本文需要了解2.2內核中ipchains的原理和使用方法作為預備知識,若你沒有這方面的知識,請閱讀IPCHAINS-HOWTO。
一、什麼是Netfilter
Netfilter比以前任何一版Linux內核的防火牆子系統都要完善強大。Netfilter提供了一個抽象、通用化的框架,該框架定義的一個子功能的實現就是包過濾子系統。因此不要在2.4中期望討論諸如"如何在2.4中架設一個防火牆或者偽裝網關"這樣的話題,這些只是Netfilter功能的一部分。Netfilter框架包含以下三部分:
1.為每種網絡協議(IPv4、IPv6等)定義一套鉤子函數(IPv4定義了5個鉤子函數),這些鉤子函數在數據報流過協議棧的幾個關鍵點被調用。在這幾個點中,協議棧將把數據報及鉤子函數標號作為參數調用netfilter框架。
2.內核的任何模塊可以對每種協議的一個或多個鉤子進行注冊,實現掛接,這樣當某個數據包被傳遞給netfilter框架時,內核能檢測是否有任何模塊對該協議和鉤子函數進行了注冊。若注冊了,則調用該模塊的注冊時使用的回調函數,這樣這些模塊就有機會檢查(可能還會修改)該數據包、丟棄該數據包及指示netfilter將該數據包傳入用戶空間的隊列。
3.那些排隊的數據包是被傳遞給用戶空間的異步地進行處理。一個用戶進程能檢查數據包,修改數據包,甚至可以重新將該數據包通過離開內核的同一個鉤子函數中注入到內核中。
所有的包過濾/NAT等等都基於該框架。內核網絡代碼中不再有到處都是的、混亂的修改數據包的代碼了。當前netfilter框架在IPv4、IPv6及Decnet網絡棧中被實現。
二、為什麼需要Netfilter
其實這個問題也可以變為ipchains有什麼缺點導致被拋棄?下面只是其中的幾個原因:
因為基於2.2內核的ipchains沒有提供傳遞數據包到用戶空間的框架,所以任何需要對數據包進行處理的代碼都必須運行在內核空間,而內核編程卻非常復雜,而且只能用C語言實現,並且容易出現錯誤並對內核穩定性造成威脅。
透明代理實現非常復雜,必須查看每個數據包來判斷是否有專門處理該地址的socket。網絡棧代碼中在11個文件中共出現了34個"#ifdef"條件編譯。
創建一個不依賴於接口地址的數據報過濾規則是不可能實現的。我們必須利用本地接口地址來判斷數據報是本地發出、還是發給本地的或是轉發的。轉發鏈只有輸出接口的信息,因此管理員必需考慮數據報的源。
偽裝和數據包過濾都在同一個模塊內實現,導致防火牆代碼過於復雜。
IPchains代碼即不模塊化又不易於擴展(例如對mac地址的過濾)
三、Netfilter的作者
Netfilter框架的概念的提出及主要實現是由Rusty Russell完成的,他是ipchains的合作完成者及當前linux內核IP防火牆的維護者。還有Marc BoUCher、James Morris、Harald Welte等都參與了Netfilter項目。
四、Netfilter在IPv4中的結構
一個數據包按照如下圖所示的過程通過Netfilter系統:
--->[1]--->[ROUTE]--->[3]--->[4]--->
^
local
[ROUTE]
v
[2] [5]
^
v
從圖中可以看到IPv4一共有5個鉤子函數,分別為:
1 NF_IP_PRE_ROUTING
2 NF_IP_LOCAL_IN
3 NF_IP_FORWARD
4 NF_IP_POST_ROUTING
5 NF_IP_LOCAL_OUT
數據報從左邊進入系統,進行IP校驗以後,數據報經過第一個鉤子函數NF_IP_PRE_ROUTING[1]進行處理;然後就進入路由代碼,其決定該數據包是需要轉發還是發給本機的;若該數據包是發被本機的,則該數據經過鉤子函數NF_IP_LOCAL_IN[2]處理以後然後傳遞給上層協議;若該數據包應該被轉發則它被NF_IP_FORWARD[3]處理;經過轉發的數據報經過最後一個鉤子函數NF_IP_POST_ROUTING[4]處理以後,再傳輸到網絡上。
本地產生的數據經過鉤子函數NF_IP_LOCAL_OUT [5]處理可以後,進行路由選擇處理,然後經過NF_IP_POST_ROUTING[4]處理以後發送到網絡上。
五、Netfilter基礎
從上面關於IPv4的netfilter的例子討論,可以看到鉤子函數是如何被激活的。
內核模塊可以對一個或多個這樣的鉤子函數進行注冊掛接,並且在數據報經過這些鉤子函數時被調用,從而模塊可以修改這些數據報,並向netfilter返回如下值:
NF_ACCEPT 繼續正常傳輸數據報
NF_DROP 丟棄該數據報,不再傳輸
NF_STOLEN 模塊接管該數據報,不要繼續傳輸該數據報
NF_QUEUE 對該數據報進行排隊(通常用於將數據報給用戶空間的進程進行處理)
NF_REPEAT 再次調用該鉤子函數
六、使用iptables進行數據報選擇
一個基於Netfilter框架的、稱為iptables的數據報選擇系統在Linux2.4內核中被應用,其實它就是ipchains的後繼工具,但卻有更強的可擴展性。
內核模塊可以注冊一個新的規則表(table),並要求數據報流經指定的規則表。這種數據報選擇用於實現數據報過濾(filter表),網絡地址轉換(Nat表)及數據報處理(mangle表)。
Linux2.4內核提供的這三種數據報處理功能都基於netfilter的鉤子函數和IP表。它們是獨立的模塊,相互之間是獨立的。它們都完美的集成到由Netfileter提供的框架中。
包過濾
filter表格不會對數據報進行修改,而只對數據報進行過濾。iptables優於ipchains的一個方面就是它更為小巧和快速。它是通過鉤子函數NF_IP_LOCAL_IN, NF_IP_FORWARD及NF_IP_LOCAL_OUT接入netfilter框架的。因此對於任何一個數據報只有一個地方對其進行過濾。這相對ipchains來說是一個巨大的改進,因為在ipchains中一個被轉發的數據報會遍歷三條鏈。
NAT
NAT表格監聽三個Netfilter鉤子函數:NF_IP_PRE_ROUTING、NF_IP_POST_ROUTING及NF_IP_LOCAL_OUT。 NF_IP_PRE_ROUTING實現對需要轉發的數據報的源地址進行地址轉換而NF_IP_POST_ROUTING則對需要轉發的數據包的目的地址進行地址轉換。對於本地數據報的目的地址的轉換則由NF_IP_LOCAL_OUT來實現。
NAT表格不同於filter表格,因為只有新連接的第一個數據報將遍歷表格,而隨後的數據報將根據第一個數據報的結果進行同樣的轉換處理。
NAT表格被用在源NAT,目的NAT,偽裝(其是源NAT的一個特例)及透明代理(其是目的NAT的一個特例)。
數據報處理(Packet mangling)
mangle表格在NF_IP_PRE_ROUTING和NF_IP_LOCAL_OUT鉤子中進行注冊。使用mangle表,可以實現對數據報的修改或給數據報附上一些帶外數據。當前mangle表支持修改TOS位及設置skb的nfmard字段。
七、連接跟蹤
連接跟蹤是NAT的基礎,但是已經作為一個單獨的模塊被實現。該功能用於對包過濾功能的一個擴展,使用連接跟蹤來實現“基於狀態”的防火牆。
七、連接跟蹤
連接跟蹤是NAT的基礎,但是已經作為一個單獨的模塊被實現。該功能用於對包過濾功能的一個擴展,使用連接跟蹤來實現“基於狀態”的防火牆。