天天看點

Linux 2.4.x 網絡安全架構

Linux 2.4.x 網絡安全架構

1.概述

在分析LINUX2.4.x網絡安全的實作之前先簡單介紹一下它裡面包含的幾個重要概念:netfilter、iptables、match、target、nf_sockopt_ops、網絡安全功能點的實作。詳細解釋會在後面的分析中講到。

首先是netfilter,它定義了協定棧中的檢查點和在檢查點上引用的資料結構,以及在檢查點上對這些結構引用的過程。iptables定義了實作網絡安全功能的規則的組織以及對規則的操作。一個規則中包含零個或多個match和一個target,規則組織沿用了LINUX2.2.x中的chain,rule的概念,但是增加了table的概念,這三者的關系是:table是實作某項功能所有規則的總和,chain是在某個檢查點上所引用規則的集合,rule是一個單獨的規則。match在規則中用于比對資料包中的各項參數,每個match比對特定的參數,是以一個規則中可以有多個match,這包括系統已定義的match,也包括通過核心子產品另外添加的match。target在規則中決定如何處理比對到的資料包,是以在target中實作了具體的網絡安全功能。nf_sockopt_ops是在系統調用get/setssockopt中引用的資料結構,實作使用者空間對規則的添加、删除、修改、查詢等動作。以上的結構在使用之前必須先注冊到系統中才能被引用。

LINUX2.4.x網絡安全實作了包過濾,位址轉換(包含了LINUX2.2.x中的位址僞裝和透明代理功能并有其他擴充功能),連接配接跟蹤(這是實作位址轉換的基礎,在它裡面實作了對連接配接狀态的記錄和監控,與狀态檢測類似),Mangle(這是LINUX2.4.x新增的一個功能,它對資料包進行檢查但不做禁止、丢棄或允許的判斷)。實作這些功能點需要分别注冊netfilter,iptables,match,target,nf_sockopt_ops的資料結構。如果實作其他新的功能,隻需定義相應的結構并将它注冊到系統中,并且通過使用者空間的配置工具(這個配置工具也須支援新的結構)把它加入到規則中就可以了。這些結構在規則中自動被引用。

2.netfilter

netfilter定義了協定棧中的檢查點和檢查點上引用的資料結構以及對這些資料結構引用的過程。首先看看在檢查點上引用的資料結構,如圖所示:

Linux 2.4.x 網絡安全架構

圖2.1 nf_hoo_ops資料結構的組織

圖中ns_hook_ops就是在檢查點上引用的結構。每個協定棧預先定義的8個連結清單數組用于儲存這些結構,這些連結清單與協定棧中的檢查點一一對應。在實際的應用中,這8個連結清單并不一定都被使用,比如在IPV4中,隻定義了5個檢查點,分别對應前5個連結清單。nf_hook_ops結構如下:

struct nf_hook_ops

{

            struct list_head list;

            nf_hookfn hook;         

            int pf;                

            int hooknum;          

            int priority;        

};

nf_register_hook函數将ns_hook_ops結構注冊到這些連結清單上,連結清單的索引由結構中hooknum指定。同一連結清單上的結構按優先值由小到大排列。在檢查點上引用這些結構時,以它們在連結清單上的先後順序引用。

檢查點由宏NF_HOOK定義。在檢查點上,函數nf_hook_slow調用函數nf_iterate周遊對應連結清單并調用連結清單上的結構ns_hook_ops中定義的函數。如果結構中的函數傳回NF_ACCEPT,則繼續調用下一個結構中的函數;如果結構中的函數傳回NF_DROP或NF_STOLEN或NF_QUEUE,則将這個值傳回給nf_hook_slow;如果結構中的函數傳回NF_REPEAT,則重複調用此結構上的函數;如果到了連結清單上的最後一個結構,則把這個結構中函數的傳回值傳回給ns_hook_slow。在ns_hook_slow中判斷nf_iterate的傳回值,如果是NF_ACCEPT,則允許資料包通過,并将資料包傳遞給協定棧中的下一個函數;如果是NF_DROP,則釋放資料包,協定棧流程中斷;如果是NF_STOLEN,同樣中斷協定棧的流程,但是沒有釋放這個資料包;如果是NF_QUEUE,則将這個包發送到使用者空間處理,同時中斷協定棧的流程。

檢查點分布在協定棧的流程中,下圖是IPV4中的檢查點:

Linux 2.4.x 網絡安全架構

圖2.2 IPV4中的檢查點

圖中檢查點的名稱如下:

檢查點編号 檢查點名稱 檢查點所在檔案名

1 NF_IP_PRE_ROUTING ip_input.c

2 NF_IP_LOCAL_IN ip_input.c

3 NF_IP_FORWARD ip_forward.c

4 NF_IP_POST_ROUTING ip_output.c

5 NF_IP_LOCAL_OUT ip_output.c

表2.1 IPV4中檢查點的名稱

圖中,ROUTE(1)處對收到的包做路由查找并判斷這個包是需要轉發的包還是發往本機上層的包,ROUTE(2)處查找發出包的路由。NF_IP_PRE_ROUTING處對所有傳入IP層的資料包進行檢查,在這之前,有關資料包的版本、長度、校驗和等正确性檢查已經完成。NF_IP_LOCAL_IN對發往本機上層的資料包進行檢查。請注意這兩個檢查點與LINUX2.2.x中檢查點的差別,在LINUX2.2.x沒有區分發往本機上層包和需要轉發的包,是以在做完位址解僞裝之後又調用了一次路由查找函數,為解僞裝之後的包查找路由。NF_IP_FORWARD處檢查需要轉發的資料包。NF_IP_POST_ROUTING處對所有向鍊路層傳遞的資料包進行檢查,注意在此處資料包的路由已經确定。NF_IP_LOCAL_OUT對本機發出的包進行檢查,此處的路由還沒有确定,是以可以做目的位址轉換。實作某個網絡安全功能可能需要在多個檢查點上注冊相應的結構,在後面的分析中我們可以看到具體的例子。

3. iptables

iptables實作對規則的管理和通路。它裡面有幾個重要的資料結構ipt_entry,ipt_match,ipt_target,ipt_table,用于構造規則表。還有一個重要的函數ipt_do_table,用于周遊規則表并處理規則表上的結構。

ipt_entry是規則的資料結構,如下:

struct ipt_entry

{

            struct ipt_ip ip;

            unsigned int nfcache;

            u_int16_t target_offset;   

            u_int16_t next_offset;     

            unsigned int comefrom;

            struct ipt_counters counters;   

            unsigned char elems[0];

};

在ipt_entry中ipt_ip是一個基本的match,它是固定的,用于比對資料包的源位址/源端口、目的位址/目的端口、協定等。其他的match按需要添加,個數并不固定,是以在ipt_entry有一個變長的字元數組儲存規則中match的指針,這些指針指向系統中注冊的match。每個規則有一個target,決定資料包完全比對規則後怎樣處理這個資料包,它也是一個指向系統注冊的target的指針,并且也放在前面提到的變長字元數組中。ipt_entry中的target_offset是target在規則中的偏移,偏移是從規則的起始位址到target所在位置的長度,還有一個變量next_offset訓示下一條規則偏移,它其實就是本條規則的長度。

前面提到在iptables中沿用了LINUX2.2.x中的chain和rule的概念,那麼在ipt_entry中如何區分chain和rule的哪?

我們知道chain是某個檢查點上檢查的規則的集合。除了預設的chain外,還可以建立新的chain。在iptables中,同一個chain裡的規則是連續存放的。預設的chain的最後一條規則的target是chain的policy。使用者建立的chain的最後一條規則的target的調用傳回值是NF_RETURN,周遊過程将傳回原來的chain。規則中的target也可以指定跳轉到某個使用者建立的chain上,這時它的target是ipt_stardard_target,并且這個target的verdict值大于0。如果在使用者建立的chain上沒有找到比對的規則,周遊過程将傳回到原來chain的下一條規則上。

ipt_match用于比對資料包的參數,如TCP資料包中的标志位,ICMP協定中的類型等,每個match所感興趣的參數都不一樣,是以一條規則可能有多個match。ipt_target決定在資料包完全比對規則後應做什麼樣的處理。這兩個在使用之間都必須先注冊到系統的連結清單中才能被規則引用。對這兩個資料結構不做過多分析,讀者可以自行參考源代碼。

ipt_table是規則表的資料結構,如下:

struct ipt_table

{

            struct list_head list;

            char name[IPT_TABLE_MAXNAMELEN];

            struct ipt_replace table;           

            unsigned int valid_hooks;         

            rwlock_t lock;

            struct ipt_table_info private;     

            struct module *me;

};

在ipt_table中,ipt_replace是使用者空間配置程式傳遞給核心的規則表,這個規則表不能直接使用,必須先根據它裡面包含的match和target的名稱将match和target轉換成在核心注冊的match和target的指針,還有一項重要的工作是檢查規則表中是否有循環,如果有循環,要給使用者空間的配置程式報告錯誤。轉換之後的規則表存儲在ipt_table_info中。valid_hooks訓示與這個表相關的檢查點,并把相應的位置為1。一個table中可以有多個chain,chain分為系統預設的chain(與table注冊的檢查點對應)和使用者建立的chain。所有的table都注冊放在一個連結清單中,而chain和rule則用偏移值next_offset連接配接成一個單向連結清單。使用者空間的配置工具在添加、删除規則之前先把核心中的規則表取到使用者空間,然後在使用者空間做添加或删除的動作,然後再将修改過的規則表傳遞到核心空間,由核心空間的函數完成後續的轉換和檢查。

函數ipt_do_table周遊table上的規則,其實這個函數的指針就儲存在nf_hook_ops結構中,并在檢查點上被調用。調用這個函數時須指定它周遊的table的指針和調用它的檢查點的值。檢查點的值用來定位table中預設chain的位置,前面我們提到,預設的chain是和檢查點對應的,在檢查點上檢查對應chain的規則。周遊規則,如果找到比對的規則,則調用這條規則的target中定義的函數,并将它的傳回值傳回給調用ipt_do_table的函數,如果沒有找到比對的規則,則調用預設chain上最後一條規則的target定義的函數,這個函數的傳回值就是這個chain的policy。

4. nf_sockopt_ops

前面提到LINUX2.4.x網絡安全架構支援多種協定。規則的配置和查詢通過系統調用get/setsockopt完成。在調用這兩個系統調用時,不同協定使用的參數不同,是以每個實作網絡安全功能的協定棧都定義了自己的nf_sockopt_ops結構并把它注冊系統的連結清單中。在調用get/setsockopt時根據不同的參數決定引用哪一個nf_sockopt_ops來完成真正的工作。

5.網絡安全功能點的實作

在LINUX2.4.x中實作網絡安全的功能點需要做以下幾件事情:一是定義nf_hook_ops結構,并将它注冊到netfilter中;二是定義iptable,match,target結構,并将它注冊到iptables中,如果需要還須注冊nf_sockopt_ops結構以便處理特殊的get/setsockopt參數。下圖就是IPV4中的功能點注冊到netfilter中的nf_hook_ops結構:

Linux 2.4.x 網絡安全架構

圖5.1 IPV4的功能點在各檢查點上注冊的結構

(圖中conntrack代表連接配接跟蹤;Filter代表包過濾;NAT(src)代表源位址轉換,NAT(dst)代表目的位址轉換;Mangle是LINUX2.4.x中新增的一個功能,完成對資料包的檢查,但是不對資料包做禁止或放行的判斷,與Filter不同。Mangle在LINUX 2.4.18 之前的實作中隻在NF_IP_PRE_ROUTING,NF_IP_LOCAL_OUT兩個檢查點上注冊了nf_hook_ops結構,在LINUX2.4.18之後的實作中在五個檢查點上都注冊了nf_look_ops結構。)

圖中在每個檢查點上,nf_hook_ops結構按調用的先後順序從上而下排列。可以看到相同的功能點在不同的檢查點上它的調用順序并不相同,這與功能點所做的動作有關。比如在NF_IP_LOCAL_IN上假設Conntrack在Filter之前,如果資料包的狀态在Conntrack中被記錄而在Filter中被禁止,那麼與這個資料包相關的狀态就不會完整,浪費了一個Conntrack的結構,是以應該先調用Filter,如果它的傳回值是NF_ACCEPT才調用Conntrack。

功能點上注冊的ipt_table,ipt_match,ipt_target,nf_sockopt_ops結構如下表所示:

功能點名稱 ipt_table ipt_match ipt_target nf_sockopt_ops
Filter packet_filter
Nat nat_table

ipt_snat_reg

ipt_dnat_reg

Conntrack so_getorigdst
Mangle packet_mangler

表5.1 功能點注冊的資料結構

值得指出的是連接配接跟蹤(Conntrack)沒有注冊任何規則表,說明它不需要規則來決定是否要作連接配接跟蹤。同時它又注冊了一個nf_sockopt_ops結構,這個結構處理參數SO_ORIGINAL_DST,用于得到透明代理的目的位址。有關位址轉換和連接配接跟蹤的詳細分析會在以後的文章中介紹。

6. 小結

LINUX2.4.x中的網絡安全實作比LINUX2.2.x有了明顯的進步。首先是IPV4協定棧中的檢查點的安排更加合理,避免在實作各功能點時不必要的函數調用。其次它的架構可擴充性很強。把功能實作和架構分離,使功能實作時不必修改架構而隻是注冊相應的結構就可完成。還有就是在這個網絡安全架構中實作的功能也比LINUX2.2.x豐富,支援的協定棧的數量也比LINUX2.2.x多。在這裡我們隻分析了LINUX2.4.x網絡安全實作的大概情況,具體的某個功能的實作會在後面的文章中分析,通過這些分析,我們将學會如何在LINUX2.4.x的網路安全架構中添加自己想要實作的功能,如何利用現有實作中的資源而有避免與現有的實作沖突。

作者簡介:林風,獨立撰稿人。熟悉LINUX網絡安全技術。比較感興趣的方向是網絡協定棧的實作。寫文章,是為整理思路,發現問題,與更多人分享經驗,知識,或者教訓。郵件位址是[email protected],歡迎批評,鼓勵或指正。

繼續閱讀