Netfilter是linux2.4內(nèi)核實(shí)現(xiàn)數(shù)據(jù)包過濾/數(shù)據(jù)包處理/NAT等的功能框架。該文討論了linux2.4內(nèi)核的netfilter功能框架,還對基于netfilter框架上的包過濾,NAT和數(shù)據(jù)包處理(packetmangling)進(jìn)行了討論。閱讀本文需要了解2.2內(nèi)核中ipchains的原理和使用方法作為預(yù)備知識,若你沒有這方面的知識,請閱讀IPCHAINS-HOWTO。
第一部分:Netfilter基礎(chǔ)和概念
一、什么是Netfilter
Netfilter比以前任何一版Linux內(nèi)核的防火墻子系統(tǒng)都要完善強(qiáng)大。Netfilter提供了一個抽象、通用化的框架,該框架定義的一個子功能的實(shí)現(xiàn)就是包過濾子系統(tǒng)。因此不要在2.4中期望討論諸如"如何在2.4中架設(shè)一個防火墻或者偽裝網(wǎng)關(guān)"這樣的話題,這些只是Netfilter功能的一部分。Netfilter框架包含以下三部分:
1 為每種網(wǎng)絡(luò)協(xié)議(IPv4、IPv6等)定義一套鉤子函數(shù)(IPv4定義了5個鉤子函數(shù)),這些鉤子函數(shù)在數(shù)據(jù)報流過協(xié)議棧的幾個關(guān)鍵點(diǎn)被調(diào)用。在這幾個點(diǎn)中,協(xié)議棧將把數(shù)據(jù)報及鉤子函數(shù)標(biāo)號作為參數(shù)調(diào)用netfilter框架。
2內(nèi)核的任何模塊可以對每種協(xié)議的一個或多個鉤子進(jìn)行注冊,實(shí)現(xiàn)掛接,這樣當(dāng)某個數(shù)據(jù)包被傳遞給netfilter框架時,內(nèi)核能檢測是否有任何模塊對該協(xié)議和鉤子函數(shù)進(jìn)行了注冊。若注冊了,則調(diào)用該模塊的注冊時使用的回調(diào)函數(shù),這樣這些模塊就有機(jī)會檢查(可能還會修改)該數(shù)據(jù)包、丟棄該數(shù)據(jù)包及指示netfilter將該數(shù)據(jù)包傳入用戶空間的隊(duì)列。
3 那些排隊(duì)的數(shù)據(jù)包是被傳遞給用戶空間的異步地進(jìn)行處理。一個用戶進(jìn)程能檢查數(shù)據(jù)包,修改數(shù)據(jù)包,甚至可以重新將該數(shù)據(jù)包通過離開內(nèi)核的同一個鉤子函數(shù)中注入到內(nèi)核中。
所有的包過濾/NAT等等都基于該框架。內(nèi)核網(wǎng)絡(luò)代碼中不再有到處都是的、混亂的修改數(shù)據(jù)包的代碼了。當(dāng)前netfilter框架在IPv4、IPv6及Decnet網(wǎng)絡(luò)棧中被實(shí)現(xiàn)。
二、為什么需要Netfilter?
其實(shí)這個問題也可以變?yōu)閕pchains有什么缺點(diǎn)導(dǎo)致被拋棄?下面只是其中的幾個原因:
因?yàn)榛?.2內(nèi)核的ipchains沒有提供傳遞數(shù)據(jù)包到用戶空間的框架,所以任何需要對數(shù)據(jù)包進(jìn)行處理的代碼都必須運(yùn)行在內(nèi)核空間,而內(nèi)核編程卻非常復(fù)雜,而且只能用C語言實(shí)現(xiàn),并且容易出現(xiàn)錯誤并對內(nèi)核穩(wěn)定性造成威脅。
透明代理實(shí)現(xiàn)非常復(fù)雜,必須查看每個數(shù)據(jù)包來判斷是否有專門處理該地址的socket。網(wǎng)絡(luò)棧代碼中在11個文件中共出現(xiàn)了34個"#ifdef"條件編譯。
創(chuàng)建一個不依賴于接口地址的數(shù)據(jù)報過濾規(guī)則是不可能實(shí)現(xiàn)的。我們必須利用本地接口地址來判斷數(shù)據(jù)報是本地發(fā)出、還是發(fā)給本地的或是轉(zhuǎn)發(fā)的。轉(zhuǎn)發(fā)鏈只有輸出接口的信息,因此管理員必需考慮數(shù)據(jù)報的源。
偽裝和數(shù)據(jù)包過濾都在同一個模塊內(nèi)實(shí)現(xiàn),導(dǎo)致防火墻代碼過于復(fù)雜。
IPchains代碼即不模塊化又不易于擴(kuò)展(例如對mac地址的過濾)
三、Netfilter的作者
Netfilter框架的概念的提出及主要實(shí)現(xiàn)是由RustyRussell完成的,他是ipchains的合作完成者及當(dāng)前l(fā)inux內(nèi)核IP防火墻的維護(hù)者。還有Marc Boucher、JamesMorris、Harald Welte等都參與了Netfilter項(xiàng)目。
四、Netfilter在IPv4中的結(jié)構(gòu)
一個數(shù)據(jù)包按照如下圖所示的過程通過Netfilter系統(tǒng):
--->[1]--->[ROUTE]--->[3]--->[4]--->
| ^
local| |
| [ROUTE]
v |
[2] [5]
| ^
| |
v |
從圖中可以看到IPv4一共有5個鉤子函數(shù),分別為:
1 NF_IP_PRE_ROUTING
2 NF_IP_LOCAL_IN
3 NF_IP_FORWARD
4 NF_IP_POST_ROUTING
5 NF_IP_LOCAL_OUT
數(shù)據(jù)報從左邊進(jìn)入系統(tǒng),進(jìn)行IP校驗(yàn)以后,數(shù)據(jù)報經(jīng)過第一個鉤子函數(shù)NF_IP_PRE_ROUTING[1]進(jìn)行處理;然后就進(jìn)入路由代碼,其決定該數(shù)據(jù)包是需要轉(zhuǎn)發(fā)還是發(fā)給本機(jī)的;若該數(shù)據(jù)包是發(fā)被本機(jī)的,則該數(shù)據(jù)經(jīng)過鉤子函數(shù)NF_IP_LOCAL_IN[2]處理以后然后傳遞給上層協(xié)議;若該數(shù)據(jù)包應(yīng)該被轉(zhuǎn)發(fā)則它被NF_IP_FORWARD[3]處理;經(jīng)過轉(zhuǎn)發(fā)的數(shù)據(jù)報經(jīng)過最后一個鉤子函數(shù)NF_IP_POST_ROUTING[4]處理以后,再傳輸?shù)骄W(wǎng)絡(luò)上。
本地產(chǎn)生的數(shù)據(jù)經(jīng)過鉤子函數(shù)NF_IP_LOCAL_OUT [5]處理可以后,進(jìn)行路由選擇處理,然后經(jīng)過NF_IP_POST_ROUTING[4]處理以后發(fā)送到網(wǎng)絡(luò)上。
五、Netfilter基礎(chǔ)
從上面關(guān)于IPv4的netfilter的例子討論,可以看到鉤子函數(shù)是如何被激活的。
內(nèi)核模塊可以對一個或多個這樣的鉤子函數(shù)進(jìn)行注冊掛接,并且在數(shù)據(jù)報經(jīng)過這些鉤子函數(shù)時被調(diào)用,從而模塊可以修改這些數(shù)據(jù)報,并向netfilter返回如下值:
NF_ACCEPT 繼續(xù)正常傳輸數(shù)據(jù)報
NF_DROP 丟棄該數(shù)據(jù)報,不再傳輸
NF_STOLEN 模塊接管該數(shù)據(jù)報,不要繼續(xù)傳輸該數(shù)據(jù)報
NF_QUEUE 對該數(shù)據(jù)報進(jìn)行排隊(duì)(通常用于將數(shù)據(jù)報給用戶空間的進(jìn)程進(jìn)行處理)
NF_REPEAT 再次調(diào)用該鉤子函數(shù)
六、使用iptables進(jìn)行數(shù)據(jù)報選擇
一個基于Netfilter框架的、稱為iptables的數(shù)據(jù)報選擇系統(tǒng)在Linux2.4內(nèi)核中被應(yīng)用,其實(shí)它就是ipchains的后繼工具,但卻有更強(qiáng)的可擴(kuò)展性。
內(nèi)核模塊可以注冊一個新的規(guī)則表(table),并要求數(shù)據(jù)報流經(jīng)指定的規(guī)則表。這種數(shù)據(jù)報選擇用于實(shí)現(xiàn)數(shù)據(jù)報過濾(filter表),網(wǎng)絡(luò)地址轉(zhuǎn)換(Nat表)及數(shù)據(jù)報處理(mangle表)。
Linux2.4內(nèi)核提供的這三種數(shù)據(jù)報處理功能都基于netfilter的鉤子函數(shù)和IP表。它們是獨(dú)立的模塊,相互之間是獨(dú)立的。它們都完美的集成到由Netfileter提供的框架中。
包過濾
filter表格不會對數(shù)據(jù)報進(jìn)行修改,而只對數(shù)據(jù)報進(jìn)行過濾。iptables優(yōu)于ipchains的一個方面就是它更為小巧和快速。它是通過鉤子函數(shù)NF_IP_LOCAL_IN,NF_IP_FORWARD及NF_IP_LOCAL_OUT接入netfilter框架的。因此對于任何一個數(shù)據(jù)報只有一個地方對其進(jìn)行過濾。這相對ipchains來說是一個巨大的改進(jìn),因?yàn)樵趇pchains中一個被轉(zhuǎn)發(fā)的數(shù)據(jù)報會遍歷三條鏈。
NAT
NAT表格監(jiān)聽三個Netfilter鉤子函數(shù):NF_IP_PRE_ROUTING、NF_IP_POST_ROUTING及NF_IP_LOCAL_OUT。NF_IP_PRE_ROUTING實(shí)現(xiàn)對需要轉(zhuǎn)發(fā)的數(shù)據(jù)報的源地址進(jìn)行地址轉(zhuǎn)換而NF_IP_POST_ROUTING則對需要轉(zhuǎn)發(fā)的數(shù)據(jù)包的目的地址進(jìn)行地址轉(zhuǎn)換。對于本地數(shù)據(jù)報的目的地址的轉(zhuǎn)換則由NF_IP_LOCAL_OUT來實(shí)現(xiàn)。
NAT表格不同于filter表格,因?yàn)橹挥行逻B接的第一個數(shù)據(jù)報將遍歷表格,而隨后的數(shù)據(jù)報將根據(jù)第一個數(shù)據(jù)報的結(jié)果進(jìn)行同樣的轉(zhuǎn)換處理。
NAT表格被用在源NAT,目的NAT,偽裝(其是源NAT的一個特例)及透明代理(其是目的NAT的一個特例)。
數(shù)據(jù)報處理(Packet mangling)
mangle表格在NF_IP_PRE_ROUTING和NF_IP_LOCAL_OUT鉤子中進(jìn)行注冊。使用mangle表,可以實(shí)現(xiàn)對數(shù)據(jù)報的修改或給數(shù)據(jù)報附上一些帶外數(shù)據(jù)。當(dāng)前mangle表支持修改TOS位及設(shè)置skb的nfmard字段。
七、連接跟蹤
連接跟蹤是NAT的基礎(chǔ),但是已經(jīng)作為一個單獨(dú)的模塊被實(shí)現(xiàn)。該功能用于對包過濾功能的一個擴(kuò)展,使用連接跟蹤來實(shí)現(xiàn)“基于狀態(tài)”的防火墻。
第二部分 使用iptables及netfilter進(jìn)行數(shù)據(jù)包過濾
一、概述
下面的內(nèi)容要求具有對TCP/IP,路由,防火墻及包過濾的基本概念的了解。
在第一部分已經(jīng)解釋過,filter表和三個鉤子進(jìn)行了掛接,因此提供了三條鏈進(jìn)行數(shù)據(jù)過濾。所有來自于網(wǎng)絡(luò),并且發(fā)給本機(jī)的數(shù)據(jù)報會遍歷INPUT規(guī)則鏈。所有被轉(zhuǎn)發(fā)的數(shù)據(jù)報將僅僅遍歷FORWARD規(guī)則鏈。最后,本地發(fā)出的數(shù)據(jù)報將遍歷OUTPUT鏈。
二、向規(guī)則鏈中插入規(guī)則
Linux2.4提供了一個簡潔強(qiáng)大的工具"iptables"來插入/刪除/修改規(guī)則鏈中的規(guī)則。這里并不對iptalbes進(jìn)行詳細(xì)的介紹,而只是討論它的主要的一些特性:
該命令實(shí)現(xiàn)對所有的ip表進(jìn)行處理,當(dāng)前包括filter,nat及mangle三個表格,及以后擴(kuò)展的表模塊。
該命令支持插件來支持新的匹配參數(shù)和目標(biāo)動作。因此對netfilter的任何擴(kuò)展都非常的簡單。僅僅需要編寫一個完成實(shí)際目標(biāo)動作處理的模塊和iptalbes插件(動態(tài)連接庫)來添加所需要的一切。
它有兩個實(shí)現(xiàn):iptables(IPV4)及ip6tables。兩者都基于相同的庫和基本上相同的代碼。
基本的iptables命令
一個iptables命令基本上包含如下五部分:
希望工作在哪個表上
希望使用該表的哪個鏈
進(jìn)行的操作(插入,添加,刪除,修改)
對特定規(guī)則的目標(biāo)動作
匹配數(shù)據(jù)報條件
基本的語法為:
iptables -t table -Operation chain -j target match(es)
例如希望添加一個規(guī)則,允許所有從任何地方到本地smtp端口的連接:
iptables -t filter -A INPUT -j ACCEPT -p tcp --dport smtp
當(dāng)然,還有其他的對規(guī)則進(jìn)行操作的命令如:清空鏈表,設(shè)置鏈缺省策略,添加一個用戶自定義的鏈....
基本操作:
-A 在鏈尾添加一條規(guī)則
-I 插入規(guī)則
-D 刪除規(guī)則
-R 替代一條規(guī)則
-L 列出規(guī)則
基本目標(biāo)動作,適用于所有的鏈
ACCEPT 接收該數(shù)據(jù)報
DROP 丟棄該數(shù)據(jù)報
QUEUE 排隊(duì)該數(shù)據(jù)報到用戶空間
RETURN 返回到前面調(diào)用的鏈
foobar 用戶自定義鏈
基本匹配條件,適用于所有的鏈
-p 指定協(xié)議(tcp/icmp/udp/...)
-s 源地址(ip address/masklen)
-d 目的地址(ip address/masklen)
-i 數(shù)據(jù)報輸入接口
-o 數(shù)據(jù)報輸出接口
出了基本的操作,匹配和目標(biāo)還具有各種擴(kuò)展。
三、iptables的數(shù)據(jù)報過濾匹配條件擴(kuò)展
有各種各樣的數(shù)據(jù)包選擇匹配條件擴(kuò)展用于數(shù)據(jù)包過濾。這里僅僅簡單的說明來讓你感受擴(kuò)展匹配的強(qiáng)大之處。
這些匹配擴(kuò)展給了我們強(qiáng)大的數(shù)據(jù)報匹配手段:
TCP匹配擴(kuò)展能匹配源端口,目的端口,及tcp標(biāo)記的任意組合,tcp選項(xiàng)等。
UPD匹配擴(kuò)展能匹配源端口和目的端口
ICMP匹配擴(kuò)展能匹配ICMP類型
MAC匹配擴(kuò)展能匹配接收到的數(shù)據(jù)的mac地址
MARK匹配擴(kuò)展能匹配nfmark
OWNE匹配擴(kuò)展(僅僅應(yīng)用于本地產(chǎn)生的數(shù)據(jù)報)來匹配用戶ID,組ID,進(jìn)程ID及會話ID
LIMIT擴(kuò)展匹配用來匹配特定時間段內(nèi)的數(shù)據(jù)報限制。這個擴(kuò)展匹配對于限制dos攻擊數(shù)據(jù)流非常有用。
STATE匹配擴(kuò)展用來匹配特定狀態(tài)下的數(shù)據(jù)報(由連接跟蹤子系統(tǒng)來決定狀態(tài)),可能的狀態(tài)包括:
INVALID (不匹配于任何連接)
ESTABLISHED (屬于某個已經(jīng)建立的鏈接的數(shù)據(jù)報)
NEW (建立連接的數(shù)據(jù)報)
RELATED (和某個已經(jīng)建立的連接有一定相關(guān)的數(shù)據(jù)報,例如一個ICMP錯誤消息或ftp數(shù)據(jù)連接)
TOS匹配擴(kuò)展用來匹配IP頭的TOS字段的值。
四、iptables的數(shù)據(jù)報過濾目標(biāo)動作擴(kuò)展
LOG 將匹配的數(shù)據(jù)報傳遞給syslog()進(jìn)行記錄
ULOG 將匹配的數(shù)據(jù)適用用戶空間的log進(jìn)程進(jìn)行記錄
REJECT 不僅僅丟棄數(shù)據(jù)報,同時返回給發(fā)送者一個可配置的錯誤信息
MIRROR 互換源和目的地址以后重新傳輸該數(shù)據(jù)報
第三部分 利用iptables和netfilter進(jìn)行NAT
linux以前的內(nèi)核僅僅支持有限的NAT功能,被稱為偽裝。Netfilter則支持任何一種NAT。一般來講NAT可以分為源NAT和目的NAT。
源NAT在數(shù)據(jù)報經(jīng)過NF_IP_POST_ROUTING時修改數(shù)據(jù)報的源地址。偽裝是一個特殊的SNAT。
目的NAT在數(shù)據(jù)報經(jīng)過NF_IP_LOCAL_OUT或NF_IP_PRE_ROUTING 時修改數(shù)據(jù)報目的地址。端口轉(zhuǎn)發(fā)和透明代理都是DNAT。
一、iptables的NAT目標(biāo)動作擴(kuò)展
SNAT
變換數(shù)據(jù)包的源地址。
例:
iptables -t nat -A POSTROUTING -j SNAT --to-source 1.2.3.4
MASQUERADE
用于具有動態(tài)IP地址的撥號連接的SNAT,類似于SNAT,但是如果連接斷開,所有的連接跟蹤信息將被丟棄,而去使用重新連接以后的IP地址進(jìn)行IP偽裝。
例:
iptables -t nat -A POSTROUTING -j MASQUERADE -o ppp0
DNAT
轉(zhuǎn)換數(shù)據(jù)報的目的地址,這是在PREROUTING鉤子鏈中處理的,也就是在數(shù)據(jù)報剛剛進(jìn)入時。因此Linux隨后的處理得到的都是新的目的地址。
例:
iptables -t nat -A PREROUTING -j DNAT --to-destination 1.2.3.4:8080 -p tcp --dport 80 -i eth1
REDIRECT
重定向數(shù)據(jù)報為目的為本地,和DNAT將目的地址修改為接到數(shù)據(jù)報的接口地址情況完全一樣。
例:
iptables -t nat -A PREROUTING -j REDIRECT --to-port 3128 -i eth1 -p tcp --dport 80
第四部分 利用iptables和netfilter進(jìn)行數(shù)據(jù)報處理(Packet mangling)
mangle表提供了修改數(shù)據(jù)報各個字段的值的方法。
一、針對數(shù)據(jù)包處理的目標(biāo)擴(kuò)展
MARK
設(shè)置nfmark字段的值。我們可以修改nfmark字段的值。nfmark僅僅是一個用戶定義的數(shù)據(jù)報的標(biāo)記(可以是無符號長整數(shù)范圍內(nèi)的任何值)。該標(biāo)記值用于基于策略的路由,通知ipqmpd (運(yùn)行在用戶空間的隊(duì)列分撿器守護(hù)進(jìn)程)將該數(shù)據(jù)報排隊(duì)給哪個哪個進(jìn)程等信息。
例: iptables -t mangle -A PREROUTING -j MARK --set-mark 0x0a -p tcp
TOS
設(shè)置數(shù)據(jù)報的IP頭的TOS字段值。若希望適用基于TOS的數(shù)據(jù)報調(diào)度及路由,這個功能是非常有用處的。
例: iptables -t mangle -A PREROUTING -j TOS --set-tos 0x10 -p tcp --dport ssh
第五部分 排隊(duì)數(shù)據(jù)報到用戶空間
前面已經(jīng)提到,任何時候在任何nefilter規(guī)則鏈中,數(shù)據(jù)報都可以被排隊(duì)轉(zhuǎn)發(fā)到用戶空間去。實(shí)際的排隊(duì)是由內(nèi)核模塊來完成的(ip_queue.o)。
數(shù)據(jù)報(包括數(shù)據(jù)報的原[meta]數(shù)據(jù)如nfmark和mac地址)通過netlink socket被發(fā)送給用戶空間進(jìn)程.該進(jìn)程能對數(shù)據(jù)報進(jìn)行任何處理。處理結(jié)束以后,用戶進(jìn)程可以將該數(shù)據(jù)報重新注入內(nèi)核或者設(shè)置一個對數(shù)據(jù)報的目標(biāo)動作(如丟棄等)。
這是netfilter的一個關(guān)鍵技術(shù),使用戶進(jìn)程可以進(jìn)行復(fù)雜的數(shù)據(jù)報操作。從而減輕了內(nèi)核空間的復(fù)雜度。用戶空間的數(shù)據(jù)報操作進(jìn)程能很容易的適用ntfilter提供的稱為libipq的庫來進(jìn)行開發(fā)。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點(diǎn)擊舉報。