????????? netfilter定義了協議棧中的檢查點和檢查點上引用的數據結構以及對這些數據結構引用的過程。首先看看在檢查點上引用的數據結構,如圖所看到的: ? ? ? ? ?圖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中的檢查點: ? ? ? ? ? 圖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_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結構:?
????????? 圖5.1 IPV4的功能點在各檢查點上注冊的結構
????????? (圖中conntrack代表連接跟蹤;Filter代表包過濾;NAT(src)代表源地址轉換,NAT(dst)代表目的地址轉換;Mangle是LINUX2.4.x中新增的一個功能。完畢對數據包的檢查,可是不正確數據包做禁止或放行的推斷。與Filter不同。Mangle在LINUX2.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,用于獲得透明代理的目的地址。 |