作者:林風(fēng)<droplet@163.net> 出處:http://www. 日期:2003-07-02
本文是上一篇文章《LINUX2.4.x網(wǎng)絡(luò)安全框架》的后續(xù)文章,主要分析連接跟蹤和地址轉(zhuǎn)換在LINUX2.4.x中的實現(xiàn),本文引用代碼是LINUX2.4.20。
1. 概述
在上一篇文章中我們提到LINUX2.4.x的網(wǎng)絡(luò)安全實現(xiàn)較之LINUX2.2.x有了很大的改進,其中的兩個重要改進一是增加了連接跟蹤的功能,二是增強了地址轉(zhuǎn)換功能的實現(xiàn)。由于地址轉(zhuǎn)換功能是在連接跟蹤的基礎(chǔ)上實現(xiàn)的,所以把這兩個模塊放在一起來分析。
連接跟蹤(CONNTRACK),顧名思義,就是跟蹤并且記錄連接狀態(tài)。這里的連接并不僅僅指TCP連接,它也包括UDP、ICMP等協(xié)議的虛擬連接。連接跟蹤是實現(xiàn)地址轉(zhuǎn)換的基礎(chǔ),在使用地址轉(zhuǎn)換功能時必須加載這個模塊。
增強的地址轉(zhuǎn)換實現(xiàn)了一個全功能的地址轉(zhuǎn)換模塊。在LINUX2.2.x中只有地址偽裝和透明代理,目的轉(zhuǎn)換還是在地址偽裝基礎(chǔ)上實現(xiàn)的。在LINUX2.4.x中,源轉(zhuǎn)換(SNAT)包括了地址偽裝和源地址轉(zhuǎn)換,目的轉(zhuǎn)換(DNAT)包括了透明代理和目的地址轉(zhuǎn)換,并且這些功能是在同一個框架下實現(xiàn)的,代碼結(jié)構(gòu)比以前清晰,可擴展性更強。
2. 檢查點以及檢查點上的函數(shù)
先來看看連接跟蹤和地址轉(zhuǎn)換在檢查點上注冊了相應(yīng)的結(jié)構(gòu),如圖:
[圖1.1 IPV4的功能點在各檢查點上注冊的結(jié)構(gòu)]
在圖中,我們可以看到不同的數(shù)據(jù)包所要經(jīng)過的三條路徑:
·發(fā)往本機上層的包:經(jīng)過的檢查點是NF_IP_PRE_ROUTING,NF_IP_LOCAL_IN。 ·由本機轉(zhuǎn)發(fā)的包:經(jīng)過的檢查點是NF_IP_PRE_ROUTING,NF_IP_FORWARD,NF_IP_POST_ROUTING。 ·從本機發(fā)出的包:NF_IP_LOCAL_OUT,NF_IP_POST_ROUTING。
在每一條路徑上,連接跟蹤和地址轉(zhuǎn)換都注冊了相應(yīng)的函數(shù),并創(chuàng)建與之相關(guān)的數(shù)據(jù)結(jié)構(gòu),完成其功能。每條路徑上功能點的順序如圖所示:
[圖1.2 路徑上功能點的順序]
在這個圖中,CONNTRACK代表連接跟蹤,DNAT代表目的轉(zhuǎn)換,SNAT代表源轉(zhuǎn)換,F(xiàn)ILTER代表包過慮。可以看到,CONNTRACK在路徑上出現(xiàn)了兩次,其作用是:第一個點上它創(chuàng)建連接跟蹤的結(jié)構(gòu),這個結(jié)構(gòu)會在后面的地址轉(zhuǎn)換和包過濾中被使用,在第二個點上它將連接跟蹤的結(jié)構(gòu)加到系統(tǒng)的連接表中。
檢查點上注冊的函數(shù)如下圖所示:
[圖1.3 連接跟蹤和地址轉(zhuǎn)換在檢查點上調(diào)用的函數(shù)]
圖中用粗體字標(biāo)識連接跟蹤的函數(shù),用斜體字標(biāo)識地址轉(zhuǎn)換的函數(shù),括號里面的函數(shù)名是實際調(diào)用的函數(shù)的名稱。這些函數(shù)在檢查點上被調(diào)用。下面將分析這些函數(shù)的實現(xiàn)以及其中所涉及的重要數(shù)據(jù)結(jié)構(gòu)和過程。
3. 連接跟蹤的重要數(shù)據(jù)結(jié)構(gòu)和過程
連接跟蹤記錄連接的狀態(tài),并且實現(xiàn)狀態(tài)間的轉(zhuǎn)換。連接并不只是指TCP協(xié)議連接,它也包括UDP協(xié)議和ICMP協(xié)議。當(dāng)然這只是內(nèi)核的標(biāo)準(zhǔn)實現(xiàn)中包含的協(xié)議,其他協(xié)議的連接跟蹤可以自己添加到內(nèi)核中。連接的數(shù)據(jù)結(jié)構(gòu)如下:
struct ip_conntrack { struct nf_conntrack ct_general; /* 結(jié)構(gòu)的引用計數(shù) */ struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; /* 不同方向上的計算哈希值的參數(shù)*/ volatile unsigned long status; /* 結(jié)構(gòu)的狀態(tài) */ struct timer_list timeout; struct list_head sibling_list; /* 與此結(jié)構(gòu)關(guān)聯(lián)的expect鏈表*/ unsigned int expecting; /* 與此結(jié)構(gòu)關(guān)聯(lián)的expect的數(shù)量*/ struct ip_conntrack_expect *master; /* 指向創(chuàng)建此結(jié)構(gòu)的expect */ struct ip_conntrack_helper *helper; /* 與此結(jié)構(gòu)關(guān)聯(lián)的helper */ struct nf_ct_info infos[IP_CT_NUMBER]; /* 不同狀態(tài)下由skb引用 */ union ip_conntrack_proto proto; union ip_conntrack_help help; struct { struct ip_nat_info info; union ip_conntrack_nat_help help; int masq_index; } nat; /* 與地址轉(zhuǎn)換相關(guān)的結(jié)構(gòu) */ };
在這個結(jié)構(gòu)中tuplehash[]記錄了此連接的正反兩個方向包的參數(shù),這些參數(shù)包括協(xié)議、源地址/源端口、目的地址/目的端口等,如果沒有端口,比如ICMP協(xié)議,就用它的id,type,code等代替。每個連接都根據(jù)這些參數(shù)計算哈希值并連接到一個全局的哈希表中。連接是雙向的,所以每個連接在哈希表中出現(xiàn)兩次,匹配連接和應(yīng)答兩個方向上的包。
前面說到,對不同協(xié)議,連接跟蹤記錄的參數(shù)不同,所以不同的協(xié)議定義了不同的 ip_conntrack_protocol結(jié)構(gòu)來處理與協(xié)議相關(guān)的內(nèi)容。這些結(jié)構(gòu)被注冊到一個全局的鏈表中,在使用時根據(jù)協(xié)議去查找,并調(diào)用相應(yīng)的處理函數(shù)來完成相應(yīng)的動作。下面將要講到的ip_nat_protocol的作用與此類似,它處理的是與協(xié)議相關(guān)的地址轉(zhuǎn)換方面的內(nèi)容。
不同協(xié)議連接跟蹤的過程不同。
TCP的連接跟蹤可以用下面的表來說明:(假設(shè)是A到B的TCP連接)
發(fā)包的方向 標(biāo)志位 連接狀態(tài) 說明 A--> B SYN IP_CT_NEW A發(fā)起連接 B-->A SYN/ACK IP_CT_ESTABLISHED B響應(yīng)A的連接請求 + IP_CT_IS_REPLY A-->B ACK IP_CT_ESTABLISHED A確認(rèn)B的響應(yīng)
[表2.1 TCP建立連接的狀態(tài)變遷]
這個表說明的是創(chuàng)建TCP連接所經(jīng)歷的狀態(tài)變遷。表中沒有顯示刪除TCP連接所經(jīng)歷的狀態(tài),這是因為刪除TCP連接是通過超時執(zhí)行的,任何狀態(tài)下都可以刪除連接,所以并不需要額外的狀態(tài)變遷。
對TCP連接,還有一個TCP的狀態(tài)變遷。它和連接的狀態(tài)不同,它記錄了TCP協(xié)議的狀態(tài)轉(zhuǎn)換,其中涉及更多與TCP連接相關(guān)的狀態(tài)。并且超時也是在這個狀態(tài)基礎(chǔ)上賦值的。具體的實現(xiàn)可以參考源代碼。
除了上面列出的狀態(tài)外,還有一個重要的狀態(tài)IP_CT_RELATED。這個狀態(tài)用于創(chuàng)建動態(tài)連接時使用。動態(tài)連接有兩類,一是處理使用了動態(tài)地址或端口的應(yīng)用協(xié)議;二是針對TCP、UDP、ICMP等協(xié)議的ICMP差錯報文。動態(tài)連接與原連接相關(guān),所以用了一個特殊的狀態(tài)來標(biāo)識它們。
UDP的連接跟蹤可以用下面的表來說明:
發(fā)包的方向 連接狀態(tài) 說明 A-->B IP_CT_NEW A到B的UPD包 B-->A IP_CT_ESTABLISHED B到A的UDP包(端口與A到B的包相反) + IP_CT_IS_REPLY
[表2.2 UDP的狀態(tài)變遷]
UDP本來是一個無狀態(tài)的協(xié)議,連接跟蹤記錄的的是兩個方向上的UDP包,并且不同狀態(tài)下,連接的超時值不同。
ICMP的連接跟蹤可以用下面的表來說明:
發(fā)包的方向 連接狀態(tài) 說明 A-->B IP_CT_NEW A到B的ICMP查詢包 B-->A IP_CT_ESTABLISHED B到A的對ICMP查詢包的應(yīng)答包 + IP_CT_IS_REPLY
[表2.3 ICMP的狀態(tài)變遷]
ICMP協(xié)議也是一個無狀態(tài)的協(xié)議,連接跟蹤記錄的是ICMP的查詢包和查詢應(yīng)答包,只有在記錄了查詢包的情況下才允許相應(yīng)的應(yīng)答包通過。
為了處理應(yīng)用協(xié)議里面的動態(tài)地址和端口,每個使用動態(tài)地址和端口的協(xié)議一般都定義了數(shù)據(jù)結(jié)構(gòu)ip_conntrack_helper,并把它放到一個全局的鏈表中。這類協(xié)議一般都會有控制連接和數(shù)據(jù)連接兩個不同的連接,如FTP協(xié)議。而在這個結(jié)構(gòu)中定義了匹配其協(xié)議控制連接的參數(shù),當(dāng)創(chuàng)建或更新結(jié)構(gòu)ip_conntrack時都會查找鏈表中有沒有相應(yīng)的ip_connctrack_helper結(jié)構(gòu),如果存在,就把它的指針賦給ip_conntrack里面的helper。ip_conntrack_helper里面的函數(shù)會根據(jù)協(xié)議里的地址和端口創(chuàng)建與控制連接相關(guān)的結(jié)構(gòu)ip_conntrack_expect,并且在有應(yīng)答時根據(jù)ip_conntrack_expect得到相應(yīng)數(shù)據(jù)連接的參數(shù)。ip_conntrack與ip_conntrack_expect的關(guān)系可以用下圖來表示:
[2.1 ip_conntrack和ip_conntrack_expect的關(guān)系]
在helper里并沒有直接創(chuàng)建ip_conntrack結(jié)構(gòu),而是創(chuàng)建了一個過渡的結(jié)構(gòu)ip_conntrack_expect,并把它放到了一個全局的鏈表中。接著,當(dāng)建立數(shù)據(jù)連接時,再找到這個ip_conntrack_expect結(jié)構(gòu),并把它與新建的ip_conntrack結(jié)構(gòu)連接起來。
連接跟蹤主要在ip_conntrack_in和ip_confirm這兩個函數(shù)里實現(xiàn)。在ip_conntrack_in里面創(chuàng)建ip_conntrack結(jié)構(gòu)。接下來,地址轉(zhuǎn)換改動數(shù)據(jù)包里的地址,包過濾會禁止包通過。如果這個包能夠到達ip_confirm,由它把相應(yīng)的ip_conntrack結(jié)構(gòu)加到系統(tǒng)的哈希表中。ip_conntrack_in函數(shù)在文件ip_conntrack_core.c中,下面是它的一個修改后的版本,每行前的行號與原文件里的行號相同。
unsigned int ip_conntrack_in { 804 (*pskb)->nfcache |= NFC_UNKNOWN; 823 if ((*pskb)->nfct) 824 return NF_ACCEPT; 指針pskb指向傳入函數(shù)的數(shù)據(jù)包,第804行設(shè)置這個數(shù)據(jù)包的標(biāo)記為NFC_UNKNOWN,說明它沒有被修改過。同類的標(biāo)記還有NFC_ALTERED,用于說明這個數(shù)據(jù)包已被修改過。在連接跟蹤里不會修改數(shù)據(jù)包的任何參數(shù),所以把它的標(biāo)記置為NFC_UNKNOWN。第823行檢查這個數(shù)據(jù)包是否已被檢查過了,因為已檢查過的數(shù)據(jù)包它的nfct成員指向它所屬的ip_conntrack結(jié)構(gòu)里的infos[]中的某一成員,以說明這個數(shù)據(jù)包是此連接的哪個狀態(tài)下收到的包。 827 if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { 828 *pskb = ip_ct_gather_frags(*pskb); 829 if (!*pskb) 830 return NF_STOLEN; 831 } 第827-831行進行分片重組。在LINUX2.4.x網(wǎng)絡(luò)安全的實現(xiàn)中,分片重組是自動進行的,并不需要打開像LINUX2.2.x中ip_always_defrag那樣的開關(guān)。 833 proto = ip_ct_find_proto((*pskb)->nh.iph->protocol); 836 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 837 && icmp_error_track(*pskb, &ctinfo, hooknum)) 838 return NF_ACCEPT; 第833-838行找到與數(shù)據(jù)包協(xié)議相同的ip_conntrack_protocol結(jié)構(gòu),并且如果協(xié)議是ICMP則調(diào)用icmp_error_track做特殊處理。 840 if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) 841 return NF_ACCEPT; 850 ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo); 851 if (ret == -1) { 853 nf_conntrack_put((*pskb)->nfct); 854 (*pskb)->nfct = NULL; 855 return NF_ACCEPT; 856 } 第840-856行根據(jù)數(shù)據(jù)包中的參數(shù)在全局的連接表中查找與此包匹配的連接結(jié)構(gòu)。前面說過,連接結(jié)構(gòu)在連接表中出現(xiàn)兩次,代表連接的兩個方向。如果沒有找到相應(yīng)的連接,則創(chuàng)建新的連接。新的連接創(chuàng)建之后,需要查找ip_conntrack_expect_list看看是否這個連接是與控制連接相關(guān)的數(shù)據(jù)連接。同時還要查找ip_conntrack_helper的鏈表,看看此連接是否有與之關(guān)聯(lián)的ip_conntrack_helper結(jié)構(gòu)。 858 if (ret != NF_DROP && ct->helper) { 859 ret = ct->helper->help((*pskb)->nh.iph, (*pskb)->len, ct, ctinfo); 861 if (ret == -1) { 863 nf_conntrack_put((*pskb)->nfct); 864 (*pskb)->nfct = NULL; 865 return NF_ACCEPT; 866 } 867 } 第858-867行調(diào)用與連接關(guān)聯(lián)的ip_conntrack_helper中的函數(shù)處理協(xié)議中的動態(tài)地址和端口。 ip_confirm函數(shù)實際調(diào)用的是函數(shù)__ip_conntrack_confirm,在調(diào)用之前它會先確認(rèn)相關(guān)連接是否已經(jīng)在全局的哈希表中,如果已經(jīng)在了,就返回。__ip_conntrack_confirm函數(shù)在文件ip_conntrack_core.c中,下面是它的一個修改過的版本,每行前的行號是原文件中的行號。 int__ip_conntrack_confirm(struct nf_ct_info *nfct) { 426 ct = __ip_conntrack_get(nfct, &ctinfo); 432 if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) 433 return NF_ACCEPT; 第426行從數(shù)據(jù)包的nfct變量中得到它所屬的ip_conntrack結(jié)構(gòu),第432行檢查此時的連接狀態(tài)是否是IP_CT_DIR_ORIGINAL方向,也就是創(chuàng)建此連接包的方向上的狀態(tài),如果不是,返回。 435 hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 436 repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); 第435-436行計算兩個方向上的哈希值。 448 WRITE_LOCK(&ip_conntrack_lock); 452 if (!LIST_FIND(&ip_conntrack_hash[hash], conntrack_tuple_cmp, struct ip_conntrack_tuple_hash *, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL) 456 && !LIST_FIND(&ip_conntrack_hash[repl_hash], conntrack_tuple_cmp, struct ip_conntrack_tuple_hash *, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { 460 list_prepend(&ip_conntrack_hash[hash], &ct->tuplehash[IP_CT_DIR_ORIGINAL]); 462 list_prepend(&ip_conntrack_hash[repl_hash], &ct->tuplehash[IP_CT_DIR_REPLY]); 470 WRITE_UNLOCK(&ip_conntrack_lock); 471 return NF_ACCEPT; 472 } 474 WRITE_UNLOCK(&ip_conntrack_lock); 475 return NF_DROP; }
第448-475行將連接加到全局的哈希表中。在加入之前,先要確認(rèn)它不在哈希表中,而且要把表鎖住,禁止其他內(nèi)核路徑讀或?qū)懝1?。如果加入成功,則返回NF_ACCEPT,如果不成功,則返回NF_DROP。
4. 地址轉(zhuǎn)換的重要數(shù)據(jù)結(jié)構(gòu)和過程
地址轉(zhuǎn)換與連接跟蹤緊密相關(guān)。事實上,與地址轉(zhuǎn)換相關(guān)的數(shù)據(jù)也就放在ip_conntrack結(jié)構(gòu)里面,它的內(nèi)容如下:
struct ip_nat_info { int initialized; unsigned int num_manips; /* 需要改動的tuple的個數(shù) */ struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS]; /* 在不同檢查點上修改后的地址和端口*/ const struct ip_nat_mapping_type *mtype; /* 地址轉(zhuǎn)換的類型 */ struct ip_nat_hash bysource, byipsproto; /* 鏈接到哈希表 */ struct ip_nat_helper *helper; /* 與此相關(guān)的helper */ struct ip_nat_seq seq[IP_CT_DIR_MAX]; };
結(jié)構(gòu)中manips[]保存的是修改后的地址和端口(這與協(xié)議有關(guān),比如說ICMP協(xié)議里面修改可能是id,type,code等。前面提到的ip_nat_protocol結(jié)構(gòu)就是處理與協(xié)議相關(guān)的參數(shù)的),這些地址用來替代原包中的地址或端口。
bysource,byipsproto兩個成員把它所在ip_conntrack鏈接到兩個哈希表中。這兩個哈希表,一個用于源地址轉(zhuǎn)換,一個用于目的地址轉(zhuǎn)換。
如前所述,ip_nat_helper處理應(yīng)用協(xié)議里的動態(tài)地址和端口,這個helper與前面提到的ip_conntrack_helper是配合起來使用的。ip_conntrack_helper創(chuàng)建與ip_conntrack相關(guān)的ip_conntrack_expect結(jié)構(gòu),然后再由ip_conntrack_helper修改其中的地址和端口。
完成地址轉(zhuǎn)換的主要函數(shù)是ip_nat_fn。在這個函數(shù)里,根據(jù)manips[]的信息修改包的地址或端口。manips[]里面的參數(shù)的填充主要來自兩個方面:一是匹配相應(yīng)的地址轉(zhuǎn)換規(guī)則(由ip_nat_rule_find查找),匹配到相應(yīng)的規(guī)則后,規(guī)則里的TARGET會將相應(yīng)的信息填充到manips[]中;還有一個就是由ip_conntrack_helper創(chuàng)建ip_conntrack結(jié)構(gòu),它的完整信息由ip_nat_helper里的expect函數(shù)填充。填充ip_nat_info里參數(shù)的函數(shù)是ip_nat_setup_info,在這個函數(shù)里為ip_nat_info選擇唯一的地址和端口,如果有多個可選地址,還可以做簡單的負(fù)載均衡。
ip_nat_fn函數(shù)在文件ip_nat_standalone.c中,下面是它的一個修改過的版本。
ip_nat_fn { 79 (*pskb)->nfcache |= NFC_UNKNOWN; 85 ct = ip_conntrack_get(*pskb, &ctinfo); 第79行設(shè)置skb的標(biāo)志,這個標(biāo)志是暫時的,因為地址轉(zhuǎn)換要修改數(shù)據(jù)包里的參數(shù),所以在改動之后,這個標(biāo)志會設(shè)置為NFC_ALTERED。第85行是得到與此包關(guān)聯(lián)的ip_contrack結(jié)構(gòu)。 103 switch (ctinfo) { 111 case IP_CT_NEW: 118 info = &ct->nat.info; 120 WRITE_LOCK(&ip_nat_lock); 123 if (!(info->initialized & (1 << maniptype))) { 127 if (ct->master && master_ct(ct)->nat.info.helper && master_ct(ct)->nat.info.helper->expect) { 130 ret = call_expect(master_ct(ct), pskb, hooknum, ct, info); 132 } else { 133 ret = ip_nat_rule_find(pskb, hooknum, in, out, ct, info); 135 } 第103-135行填充ip_nat_info結(jié)構(gòu),這里有兩種情況。對創(chuàng)建ip_conntrack結(jié)構(gòu)的包,因為是它的ip_nat_info結(jié)構(gòu)還沒有初始化,所以調(diào)用ip_nat_rule_find去查找相應(yīng)的地址轉(zhuǎn)換規(guī)則,這個函數(shù)又會調(diào)用ipt_do_table函數(shù)。如果這個ip_conntrack結(jié)構(gòu)是由ip_conntrack_helper創(chuàng)建的,則調(diào)用它的控制連接的ip_nat_helper中的expect函數(shù)填充數(shù)據(jù)連接中ip_nat_info中的參數(shù)。如果相應(yīng)的ip_nat_info結(jié)構(gòu)已經(jīng)填充過了,則跳過這部分處理。 142 if (in_hashes) { 144 replace_in_hashes(ct, info); 145 } else { 146 place_in_hashes(ct, info); 147 } 148 } 152 WRITE_UNLOCK(&ip_nat_lock); 第142-152行根據(jù)新的地址和端口將ip_conntrack放到全局的哈希表中,或者從哈希表中將使用舊參數(shù)的ip_conntrack取下來,并使用新的參數(shù)把它重新放到哈希表中。 163 return do_bindings(ct, ctinfo, info, hooknum, pskb); 第163行的do_bindings函數(shù)完成數(shù)據(jù)包的修改,并且如果ip_conntrack上有與之相關(guān)的ip_nat_helper,則調(diào)用的help函數(shù)處理應(yīng)用協(xié)議里的數(shù)據(jù)。
5. 連接跟蹤、地址轉(zhuǎn)換與包過濾的關(guān)系
LINUX2.4.x中的連接跟蹤和包過濾是兩個獨立的功能。連接跟蹤創(chuàng)建的連接結(jié)構(gòu)并不作為允許或禁止包通過的依據(jù),只是在包過濾中可以匹配連接跟蹤里面的狀態(tài),進而決定允許或禁止包通過。這一點與一般意義上的狀態(tài)檢測不同。在狀態(tài)檢測里面,如果有相應(yīng)的連接存在,就不檢查過濾規(guī)則,只進行相應(yīng)的狀態(tài)變遷。在LINUX2.4.x中,不管連接跟蹤的狀態(tài)如何,都要去檢查過濾規(guī)則才能決定是否允許包通過。其檢查效率要差一些。
從前面的檢查點的順序圖可以看出,包過濾是在目的轉(zhuǎn)換之后,源轉(zhuǎn)換之前進行的,所以在添加過濾規(guī)則時,規(guī)則中的目的地址要用轉(zhuǎn)換后的地址,也就是數(shù)據(jù)包真正的目的地,而不是包中原來地目的地址。
6. 小結(jié)
以上是對LINUX2.4.x中連接跟蹤和地址轉(zhuǎn)換實現(xiàn)的簡單分析。在分析中我們可以看到,在這個實現(xiàn)里面,有許多可以擴展的東西:如ip_conntrack_protocol,ip_nat_protocol,ip_conntrack_helper,ip_nat_helper等。加上上一篇介紹的ipt_table,ipt_match,ipt_target,nf_hook_ops等。LINUX2.4.x網(wǎng)絡(luò)安全的實現(xiàn)就是建立在這些可擴展結(jié)構(gòu)的基礎(chǔ)之上,所以它有很好的可擴展性。并且,針對不同的協(xié)議定義的不同的結(jié)構(gòu)處理與協(xié)議相關(guān)的信息,使得信息隱蔽性好,模塊化增強。這正是一個出色的框架所具備的特點。不過它并沒有實現(xiàn)真正意義上的狀態(tài)檢測,而且它的包過濾的效率也有待改進。
參考資料:
1:LINUX2.4.20內(nèi)核源代碼
2:Netfilter Hacking HOWTO
2: iptables tutorial by Oskar Andreasson
3:Iptables connection tracking by James C. Stephens.
作者簡介:
林風(fēng),獨立撰稿人。熟悉LINUX網(wǎng)絡(luò)安全技術(shù)。比較感興趣的方向是網(wǎng)絡(luò)協(xié)議棧的實現(xiàn)。寫文章,是為整理思路,發(fā)現(xiàn)問題,與更多人分享經(jīng)驗,知識,或者教訓(xùn)。郵件地址是droplet@163.net,歡迎批評,鼓勵或指正。 |
|
|
|
|
|