1. 程式人生 > >Linux核心工程導論——網路:Netfilter概覽

Linux核心工程導論——網路:Netfilter概覽

簡介

最早的核心包過濾機制是ipfwadm,後來是ipchains,再後來就是iptables/netfilter了。再往後,也就是現在是nftables。不過nftables與iptables還處於爭雄階段,誰能勝出目前還沒有定論。但是他們都屬於netfilter專案的子成員。

鉤子

         netfilter基於鉤子,在核心網路協議棧的幾個固定的位置由netfilter的鉤子。我們知道資料包有兩種流向,一種是給本機的:驅動接收——》路由表——》本機協議棧——》驅動傳送。一種是要轉發給別人的:驅動接收——》路由表——》轉發——》驅動傳送。針對這幾個關鍵位置,netfilter定義了幾個鉤子:NF_IP_PRE_ROUTING是在查路由表之前,NF_IP_LOCAL_IN實在查完路由表決定傳送本機之後,NF_IP_FORWARD實在查完路由表決定轉發的時候,NF_IP_POST_ROUTING是要交給驅動傳送之前,NF_IP_LOCAL_OUT是本機產生的資料交給驅動傳送之前。通過在這幾個鉤子位置註冊函式,截斷資料包的流動,可以完成資料包的過濾和轉換功能。要知道的是,轉發功能一般只在路由器上開啟,一般的PC如果發現不是自己的資料包就會直接選擇丟棄。所以,普通PC可以使用的鉤子有NF_IP_PRE_ROUTING、NF_IP_LOCAL_IN、NF_IP_LOCAL_OUT、NF_IP_POST_ROUTING四個。可以看到都是在IP層的鉤子,然而,這些鉤子可不僅只可以處理IP層的資料,因為在IP層可以拿到完整的資料包,所以你想處理哪一層都是可以的。

         iptables不是註冊在鉤子函式上,但是位置是一致的。是netfilter框架下的一個附屬的功能,由table、chain、rule組成。

         netfilter提供了幾個重要的功能,方便無論是iptables還是nftables使用。caching功能可以有一個快取,通過查詢資料包的某個位置可以決定該資料包根本不會經過後面的過濾規則。

使用者空間使用iptables

table、chain和rule

         chain和rule是iptables自創的概念,我們知道在鉤子函式的地方可以執行指定的函式呼叫。iptables系統就預設實現了幾個呼叫,並且用統一的資料結構來組織這個呼叫的形式。這個組織結構就是table、chain和rule。

         在任何一個hook點,都可以定義多個table,一個table有多個chain,每個chain中可以定義多個rule。要記住的是table和chain只是容器,裡面的rule才是真正發揮作用的規則。理論上我們可以在任何一個hook點做過濾、nat、修改資料包等所有操作,但是iptables為了統一架構起見,在各個hook點定義了順序的幾個table,每個table用來完成一類的工作。預定義的table包括:filter、nat和mangle。這每一個table表示的是功能,並不是表示位置,一個table內部有多個chain,其中每個chain位於特定的位置。

下圖是一個內部已經定義的table、chain關係圖表:

https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg


FILTER: PREROUTING, FORWARD, POSTROUTING

NAT: PREROUTING, INPUT, OUTPUT, POSTROUTING

MANGLE: PREROUTING, INPUT, FORWARD, OUTPUT,POSTROUTING

         可以看到,預定義的3個表表示3種不同的功能,每個表都在一些hook點定義了一組chain。如此,當一個使用者想要在某一個hook點做某一件事情,就可以定位到table(功能)——》chain(位置)——rule(行為)來完成資料包操作。

         每一條rule的格式都是相同的,包括源IP地址、目的IP地址、上層協議、介面、操作(target)。但是並不是每個域對於每個chain都是可用的,例如在INPUT的地方匹配輸出介面就是永遠匹配不到的。所以有效的rule在不同的chain上是不同的。

         iptables是個可擴充套件的軟體,其對TCP、UDP等常用協議的支援都是通過擴充套件,iptables本體只支援到ip層,你只要使用對應的選項就會自動的使用擴充套件。還有一些不是協議的擴充套件,這些擴充套件一般通過iptables –m 呼叫,例如iptables –m mac可以用來匹配mac地址。-m limit可以用來限制每秒鐘匹配的數目,超過的就放行。這些擴充套件包括:

l  xt_mac.ko:匹配mac地址

l  xt_limit.ko:限制每秒鐘匹配的數目,超過的就放行

l  xt_owner.ko:用來匹配某個某個程序或使用者建立的資料包

l  xt_state.ko:用來匹配處於某個連線狀態的資料包(例如NEW、ESTABLLISHED、RELATED)

l  xt_pkttype.ko:用來根據多播、廣播還是單播來匹配包

l  xt_quota.ko:可以為一個rule設定quota,當quota達到後,改rule失效

l  xt_recent.ko:允許你設定一個IP列表,後續的IP列表的使用者都不生效

l  xt_string.ko:允許你匹配資料包中的一個字串

l  xt_time.ko:允許你根據資料包的到達和離去時間進行匹配

l  xt_u32.ko:通過匹配檢查資料包的某4位是否與要求的一致來進行操作

還有很多target的擴充套件和conntrack的擴充套件、ipv6的擴充套件。可以根據應用的型別進行匹配,可以修改ttl、TOS等資料位。基本能用得上的功能都有對應的擴充套件。

操作(target)也是可以擴充套件的,常見的預設的操作有ACCEPT和DROP,擴充套件的還有LOG、REJECT等,使用者還可以自己實現。還有兩種預設是QUEUE和RETURN,RETURN實現了各個規則之間的函式式呼叫,QUEUE則實現了資料包的排隊。這些操作也都對應著具體的模組:nft_queue.ko、nft_reject.ko、xt_LOG.ko、nft_log.ko等。

bpf

使用者空間不止可以新增規則,還可以新增程式碼。這是通過xt_bpf模組實現的。iptables –m bpf –bytecode 後面跟具體的code就好了,從彙編編譯成code的程式再linux核心的tool/net下有。

核心模組使用netfilter

         不但是使用者空間可以給iptables新增規則,核心模組新增規則的能力更強大。由於其具備編碼能力,所以不只是可以丟棄一個數據包,還可以返回NF_STOLEN,這樣這個資料包對於協議棧來說將會停止向上傳送,而這個模組將會處理這個資料包的後續流程。

         應該注意的是,netfilter這個名字指的是核心過濾資料包這個架構,而iptables則是table、chain、rule這套設計。核心裡面一般直接使用netfilter的鉤子,而不使用iptables的規則。