Linux 2.4中netfilter框架實現(轉)

post0發表於2007-08-10
Linux 2.4中netfilter框架實現(轉)[@more@]

Netfilter是linux2.4核心實現資料包過濾/資料包處理/NAT等的功能框架。該文討論了linux 2.4核心的netfilter功能框架,還對基於netfilter框架上的包過濾,NAT和資料包處理(packet mangling)進行了討論。閱讀本文需要了解2.2核心中ipchains的原理和使用方法作為預備知識,若你沒有這方面的知識,請閱讀IPCHAINS-HOWTO。

第一部分:Netfilter基礎和概念

一、什麼是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系統:

---&gt[1]---&gt[ROUTE]---&gt[3]---&gt[4]---&gt

| ^

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的基礎,但是已經作為一個單獨的模組被實現。該功能用於對包過濾功能的一個擴充套件,使用連線跟蹤來實現“基於狀態”的防火牆。

第二部分 使用iptables及netfilter進行資料包過濾

一、概述

下面的內容要求具有對TCP/IP,路由,防火牆及包過濾的基本概念的瞭解。

在第一部分已經解釋過,filter表和三個鉤子進行了掛接,因此提供了三條鏈進行資料過濾。所有來自於網路,並且發給本機的資料包會遍歷INPUT規則鏈。所有被轉發的資料包將僅僅遍歷FORWARD規則鏈。最後,本地發出的資料包將遍歷OUTPUT鏈。

二、向規則鏈中插入規則

Linux2.4提供了一個簡潔強大的工具"iptables"來插入/刪除/修改規則鏈中的規則。這裡並不對iptalbes進行詳細的介紹,而只是討論它的主要的一些特性:

該命令實現對所有的ip表進行處理,當前包括filter,nat及mangle三個表格,及以後擴充套件的表模組。

該命令支援外掛來支援新的匹配引數和目標動作。因此對netfilter的任何擴充套件都非常的簡單。僅僅需要編寫一個完成實際目標動作處理的模組和iptalbes外掛(動態連線庫)來新增所需要的一切。

它有兩個實現:iptables(IPV4)及ip6tables。兩者都基於相同的庫和基本上相同的程式碼。

基本的iptables命令

一個iptables命令基本上包含如下五部分:

希望工作在哪個表上

希望使用該表的哪個鏈

進行的操作(插入,新增,刪除,修改)

對特定規則的目標動作

匹配資料包條件

基本的語法為:

iptables -t table -Operation chain -j target match(es)

例如希望新增一個規則,允許所有從任何地方到本地smtp埠的連線:

iptables -t filter -A INPUT -j ACCEPT -p tcp --dport smtp

當然,還有其他的對規則進行操作的命令如:清空連結串列,設定鏈預設策略,新增一個使用者自定義的鏈....

基本操作:

-A 在鏈尾新增一條規則

-I 插入規則

-D 刪除規則

-R 替代一條規則

-L 列出規則

基本目標動作,適用於所有的鏈

ACCEPT 接收該資料包

DROP 丟棄該資料包

QUEUE 排隊該資料包到使用者空間

RETURN 返回到前面呼叫的鏈

foobar 使用者自定義鏈

基本匹配條件,適用於所有的鏈

-p 指定協議(tcp/icmp/udp/...)

-s 源地址(ip address/masklen)

-d 目的地址(ip address/masklen)

-i 資料包輸入介面

-o 資料包輸出介面

出了基本的操作,匹配和目標還具有各種擴充套件。

三、iptables的資料包過濾匹配條件擴充套件

有各種各樣的資料包選擇匹配條件擴充套件用於資料包過濾。這裡僅僅簡單的說明來讓你感受擴充套件匹配的強大之處。

這些匹配擴充套件給了我們強大的資料包匹配手段:

TCP匹配擴充套件能匹配源埠,目的埠,及tcp標記的任意組合,tcp選項等。

UPD匹配擴充套件能匹配源埠和目的埠

ICMP匹配擴充套件能匹配ICMP型別

MAC匹配擴充套件能匹配接收到的資料的mac地址

MARK匹配擴充套件能匹配nfmark

OWNE匹配擴充套件(僅僅應用於本地產生的資料包)來匹配使用者ID,組ID,程式ID及會話ID

LIMIT擴充套件匹配用來匹配特定時間段內的資料包限制。這個擴充套件匹配對於限制dos攻擊資料流非常有用。

STATE匹配擴充套件用來匹配特定狀態下的資料包(由連線跟蹤子系統來決定狀態),可能的狀態包括:

INVALID (不匹配於任何連線)

ESTABLISHED (屬於某個已經建立的連結的資料包)

NEW (建立連線的資料包)

RELATED (和某個已經建立的連線有一定相關的資料包,例如一個ICMP錯誤訊息或ftp資料連線)

TOS匹配擴充套件用來匹配IP頭的TOS欄位的值。

四、iptables的資料包過濾目標動作擴充套件

LOG 將匹配的資料包傳遞給syslog()進行記錄

ULOG 將匹配的資料適用使用者空間的log程式進行記錄

REJECT 不僅僅丟棄資料包,同時返回給傳送者一個可配置的錯誤資訊

MIRROR 互換源和目的地址以後重新傳輸該資料包

第三部分 利用iptables和netfilter進行NAT

linux以前的核心僅僅支援有限的NAT功能,被稱為偽裝。Netfilter則支援任何一種NAT。一般來講NAT可以分為源NAT和目的NAT。

源NAT在資料包經過NF_IP_POST_ROUTING時修改資料包的源地址。偽裝是一個特殊的SNAT。

目的NAT在資料包經過NF_IP_LOCAL_OUT或NF_IP_PRE_ROUTING 時修改資料包目的地址。埠轉發和透明代理都是DNAT。

一、iptables的NAT目標動作擴充套件

SNAT

變換資料包的源地址。

例:

iptables -t nat -A POSTROUTING -j SNAT --to-source 1.2.3.4

MASQUERADE

用於具有動態IP地址的撥號連線的SNAT,類似於SNAT,但是如果連線斷開,所有的連線跟蹤資訊將被丟棄,而去使用重新連線以後的IP地址進行IP偽裝。

例:

iptables -t nat -A POSTROUTING -j MASQUERADE -o ppp0

DNAT

轉換資料包的目的地址,這是在PREROUTING鉤子鏈中處理的,也就是在資料包剛剛進入時。因此Linux隨後的處理得到的都是新的目的地址。

例:

iptables -t nat -A PREROUTING -j DNAT --to-destination 1.2.3.4:8080 -p tcp --dport 80 -i eth1

REDIRECT

重定向資料包為目的為本地,和DNAT將目的地址修改為接到資料包的介面地址情況完全一樣。

例:

iptables -t nat -A PREROUTING -j REDIRECT --to-port 3128 -i eth1 -p tcp --dport 80

 

第四部分 利用iptables和netfilter進行資料包處理(Packet mangling)

mangle表提供了修改資料包各個欄位的值的方法。

一、針對資料包處理的目標擴充套件

MARK

設定nfmark欄位的值。我們可以修改nfmark欄位的值。nfmark僅僅是一個使用者定義的資料包的標記(可以是無符號長整數範圍內的任何值)。該標記值用於基於策略的路由,通知ipqmpd (執行在使用者空間的佇列分撿器守護程式)將該資料包排隊給哪個哪個程式等資訊。

例: iptables -t mangle -A PREROUTING -j MARK --set-mark 0x0a -p tcp

TOS

設定資料包的IP頭的TOS欄位值。若希望適用基於TOS的資料包排程及路由,這個功能是非常有用處的。

例: iptables -t mangle -A PREROUTING -j TOS --set-tos 0x10 -p tcp --dport ssh

第五部分 排隊資料包到使用者空間

前面已經提到,任何時候在任何nefilter規則鏈中,資料包都可以被排隊轉發到使用者空間去。實際的排隊是由核心模組來完成的(ip_queue.o)。

資料包(包括資料包的原[meta]資料如nfmark和mac地址)透過netlink socket被髮送給使用者空間程式.該程式能對資料包進行任何處理。處理結束以後,使用者程式可以將該資料包重新注入核心或者設定一個對資料包的目標動作(如丟棄等)。

這是netfilter的一個關鍵技術,使使用者程式可以進行復雜的資料包操作。從而減輕了核心空間的複雜度。使用者空間的資料包操作程式能很容易的適用ntfilter提供的稱為libipq的庫來進行開發。

參考文獻:

LaForge's talk about Netfilter

The netfilter framework in Linux 2.4

Linux 2.4 Packet Filtering HOWTO

Linux 2.4 NAT HOWTO

netfilter hacking HOWTO

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-940617/,如需轉載,請註明出處,否則將追究法律責任。

相關文章