免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
netfilter中IP協(xié)議跟蹤和NAT實(shí)現(xiàn)
netfilter中IP協(xié)議跟蹤和NAT實(shí)現(xiàn)

本文檔的Copyleft歸yfydz所有,使用GPL發(fā)布,可以自由拷貝,轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)保持文檔的完整性,嚴(yán)禁用于任何商業(yè)用途。
msn: [email]yfydz_no1@hotmail.com[/email]
來(lái)源:[url]http://yfydz.cublog.cn[/url]

1. 前言

和匹配和目標(biāo)一樣,netfilter提供了模塊化的IP層協(xié)議的跟蹤和NAT處理,除了內(nèi)核自帶的模塊外,用戶可以根據(jù)模塊格式自己編寫其他IP協(xié)議的跟蹤和NAT處理。注意:本文針對(duì)的跟蹤和NAT模塊是針對(duì)IP上層的協(xié)議,如TCP、UDP、ICMP等,而TCP、UDP上層的協(xié)議如FTP、TFTP等的跟蹤和NAT使用其他方式處理,將在以后的文章中介紹。

2. tuple

在具體介紹IP協(xié)議跟蹤前,需要說(shuō)明一個(gè)結(jié)構(gòu)ip_conntrack_tuple,這是netfilter用來(lái)描述跟蹤或NAT各IP協(xié)議時(shí)需要跟蹤或修改的各協(xié)議的信息,這些信息和連接的一一對(duì)應(yīng)的,對(duì)于所有IP協(xié)議,協(xié)議類型、源地址、目的地址這三個(gè)參數(shù)是識(shí)別連接所必須的,具體到各個(gè)協(xié)議,就要提取出各協(xié)議的唯一特征數(shù)據(jù),如TCP、UDP的源端口、目的端口,ICMP的ID、TYPE、CODE等值,這些值就是tuple結(jié)構(gòu)要處理的數(shù)據(jù)。各協(xié)議相關(guān)數(shù)據(jù)是以聯(lián)合形式定義在tuple結(jié)構(gòu)中的,netfilter缺省支持TCP、UDP和ICMP協(xié)議,如果還要支持其他IP協(xié)議,如GRE、ESP、AH、SCTP等,需要在聯(lián)合中添加相應(yīng)的協(xié)議參數(shù)值。

include/linux/netfilter_ipv4/ip_conntrack_tuple.h
/* The protocol-specific manipulable parts of the tuple: always in
   network order! */
union ip_conntrack_manip_proto
{
/* Add other protocols here. */
u_int16_t all;
struct {
  u_int16_t port;
} tcp;
struct {
  u_int16_t port;
} udp;
struct {
  u_int16_t id;
} icmp;
};
/* The manipulable part of the tuple. */
struct ip_conntrack_manip
{
u_int32_t ip;
union ip_conntrack_manip_proto u;
};

/* This contains the information to distinguish a connection. */
struct ip_conntrack_tuple
{
struct ip_conntrack_manip src;
/* These are the parts of the tuple which are fixed. */
struct {
  u_int32_t ip;
  union {
   /* Add other protocols here. */
   u_int16_t all;
   struct {
    u_int16_t port;
   } tcp;
   struct {
    u_int16_t port;
   } udp;
   struct {
    u_int8_t type, code;
   } icmp;
  } u;
  /* The protocol. */
  u_int16_t protonum;
} dst;
};

3. 協(xié)議連接跟蹤

netfilter中對(duì)每個(gè)要進(jìn)行跟蹤的IP協(xié)議定義了以下結(jié)構(gòu),每個(gè)IP協(xié)議的連接跟蹤處理就是要填寫這樣一個(gè)結(jié)構(gòu):

include/linux/netfilter_ipv4/ip_conntrack_protocol.h
struct ip_conntrack_protocol
{
/* Next pointer. */
struct list_head list;
/* Protocol number. */
u_int8_t proto;
/* Protocol name */
const char *name;
/* Try to fill in the third arg; return true if possible. */
int (*pkt_to_tuple)(const void *datah, size_t datalen,
       struct ip_conntrack_tuple *tuple);
/* Invert the per-proto part of the tuple: ie. turn xmit into reply.
  * Some packets can‘t be inverted: return 0 in that case.
  */
int (*invert_tuple)(struct ip_conntrack_tuple *inverse,
       const struct ip_conntrack_tuple *orig);
/* Print out the per-protocol part of the tuple. */
unsigned int (*print_tuple)(char *buffer,
        const struct ip_conntrack_tuple *);
/* Print out the private part of the conntrack. */
unsigned int (*print_conntrack)(char *buffer,
     const struct ip_conntrack *);
/* Returns verdict for packet, or -1 for invalid. */
int (*packet)(struct ip_conntrack *conntrack,
        struct iphdr *iph, size_t len,
        enum ip_conntrack_info ctinfo);
/* Called when a new connection for this protocol found;
  * returns TRUE if it‘s OK.  If so, packet() called next. */
int (*new)(struct ip_conntrack *conntrack, struct iphdr *iph,
     size_t len);
/* Called when a conntrack entry is destroyed */
void (*destroy)(struct ip_conntrack *conntrack);
/* Has to decide if a expectation matches one packet or not */
int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
          struct sk_buff **pskb);
/* Module (if any) which this is connected to. */
struct module *me;
};

結(jié)構(gòu)中包括以下參數(shù):

struct list_head list:這是將該結(jié)構(gòu)掛接到協(xié)議跟蹤鏈表中的
u_int8_t proto:協(xié)議號(hào),在IP頭中的協(xié)議號(hào)是8位,1為ICMP,2為IGMP,6為TCP,17為UDP等等
const char *name:協(xié)議名稱,字符串常量
struct module *me:指向模塊本身,統(tǒng)計(jì)模塊是否被使用

結(jié)構(gòu)中包括以下函數(shù):

(*pkt_to_tuple):將數(shù)據(jù)包中的信息提取到tuple結(jié)構(gòu)中,如對(duì)于TCP/UDP,提取其端口值,在net/ipv4/netfilter/ip_conntrack_core.c的get_tuple()函數(shù)中調(diào)用;

(*invert_tuple):將tuple中數(shù)據(jù)進(jìn)行倒置,用來(lái)匹配處理連接的返回包,如對(duì)于TCP/UDP,要將端口值倒置,在net/ipv4/netfilter/ip_conntrack_core.c的invert_tuple()函數(shù)中調(diào)用;

(*print_tuple):打印協(xié)議相關(guān)的tuple值,在查看/proc/net/ip_conntrack文件時(shí)調(diào)用,net/ipv4/netfilter/ip_conntrack_standalone.c;

(*print_conntrack):打印協(xié)議相關(guān)的值,在查看/proc/net/ip_conntrack文件時(shí)調(diào)用,net/ipv4/netfilter/ip_conntrack_standalone.c;

(*packet):判斷數(shù)據(jù)包是否合法,并調(diào)整相應(yīng)連接的信息,也就是實(shí)現(xiàn)各協(xié)議的狀態(tài)檢測(cè),對(duì)于UDP等本身是無(wú)連接的協(xié)議的判斷比較簡(jiǎn)單,netfilter建立一個(gè)虛擬連接,每個(gè)新發(fā)包都是合法包,只等待回應(yīng)包到后連接都結(jié)束;但對(duì)于TCP之類的有狀態(tài)協(xié)議必須檢查數(shù)據(jù)是否符合協(xié)議的狀態(tài)轉(zhuǎn)換過(guò)程,這是靠一個(gè)狀態(tài)轉(zhuǎn)換數(shù)組實(shí)現(xiàn)的,在我以前的文章“什么是狀態(tài)檢測(cè)”中對(duì)這個(gè)數(shù)組進(jìn)行了描述。在net/ipv4/netfilter/ip_conntrack_core.c的ip_conntrack_in()函數(shù)中調(diào)用;

(*new):判斷是否是該協(xié)議的新連接,如對(duì)于TCP,必須用SYN包表示連接開始,而對(duì)于UDP和ICMP則始終是新連接,在net/ipv4/netfilter/ip_conntrack_core.c的init_conntrack()函數(shù)中調(diào)用;

(*destroy):在系統(tǒng)刪除連接時(shí)釋放該協(xié)議的特定數(shù)據(jù),不過(guò)目前都沒(méi)有使用,在net/ipv4/netfilter/ip_conntrack_core.c的destroy_conntrack()函數(shù)中調(diào)用;

(*exp_matches_pkt):判斷該數(shù)據(jù)包是否是期待的新包還是以前的重發(fā)包,只是在NAT處理時(shí)使用,針對(duì)的是有序列號(hào)控制的協(xié)議,如TCP,而無(wú)序列號(hào)控制的協(xié)議無(wú)此函數(shù)處理,在net/ipv4/netfilter/ip_nat_core.c的exp_for_packet()函數(shù)中調(diào)用;
最后,這些協(xié)議跟蹤結(jié)構(gòu)在net/ipv4/netfilter/ip_conntrack_core.c的

ip_conntrack_init()函數(shù)中掛接到協(xié)議跟蹤鏈表中:
list_append(&protocol_list, &ip_conntrack_protocol_tcp);
list_append(&protocol_list, &ip_conntrack_protocol_udp);
list_append(&protocol_list, &ip_conntrack_protocol_icmp);

要編寫自己的IP協(xié)議跟蹤模塊,先要分析這些協(xié)議頭中哪些信息可以用來(lái)唯一識(shí)別連接,作NAT時(shí)要修改哪些信息,把這些信息添加到ip_conntrack_tuple結(jié)構(gòu)的聯(lián)合中;然后填寫該協(xié)議的ip_conntrack_protocol結(jié)構(gòu),實(shí)現(xiàn)結(jié)構(gòu)中的內(nèi)部函數(shù);最后在ip_conntrack_init()函數(shù)中將此結(jié)構(gòu)掛接到協(xié)議跟蹤鏈表中。

4. 協(xié)議NAT

netfilter中對(duì)每個(gè)要進(jìn)行NAT的IP協(xié)議定義了以下結(jié)構(gòu),每個(gè)IP協(xié)議的NAT處理就是要填寫這樣一個(gè)結(jié)構(gòu):

include/linux/netfilter_ipv4/ip_nat_protocol.h
struct ip_nat_protocol
{
struct list_head list;
/* Protocol name */
const char *name;
/* Protocol number. */
unsigned int protonum;
/* Do a packet translation according to the ip_nat_proto_manip
  * and manip type. */
void (*manip_pkt)(struct iphdr *iph, size_t len,
     const struct ip_conntrack_manip *manip,
     enum ip_nat_manip_type maniptype);
/* Is the manipable part of the tuple between min and max incl? */
int (*in_range)(const struct ip_conntrack_tuple *tuple,
   enum ip_nat_manip_type maniptype,
   const union ip_conntrack_manip_proto *min,
   const union ip_conntrack_manip_proto *max);
/* Alter the per-proto part of the tuple (depending on
    maniptype), to give a unique tuple in the given range if
    possible; return false if not.  Per-protocol part of tuple
    is initialized to the incoming packet. */
int (*unique_tuple)(struct ip_conntrack_tuple *tuple,
       const struct ip_nat_range *range,
       enum ip_nat_manip_type maniptype,
       const struct ip_conntrack *conntrack);
unsigned int (*print)(char *buffer,
         const struct ip_conntrack_tuple *match,
         const struct ip_conntrack_tuple *mask);
unsigned int (*print_range)(char *buffer,
        const struct ip_nat_range *range);
};

結(jié)構(gòu)中包括以下參數(shù):

struct list_head list:這是將該結(jié)構(gòu)掛接到協(xié)議跟蹤鏈表中的
const char *name:協(xié)議名稱,字符串常量
unsigned int protonum:協(xié)議號(hào),在IP頭中的協(xié)議號(hào)是8位,在此用unsigned int有點(diǎn)浪費(fèi)

結(jié)構(gòu)中包括以下函數(shù):

(*manip_pkt):修改協(xié)議相關(guān)數(shù)據(jù),根據(jù)NAT規(guī)則來(lái)確定是修改源部分還是目的部分,在net/ipv4/netfilter/ip_nat_core.c的manip_pkt()函數(shù)中調(diào)用;

(*in_range):判斷數(shù)據(jù)包是否是要進(jìn)行NAT修改,在net/ipv4/netfilter/ip_nat_core.c的in_range()、get_unique_tuple()等函數(shù)中調(diào)用;

(*unique_tuple):構(gòu)造一個(gè)新tuple處理將原tuple在進(jìn)行NAT后對(duì)應(yīng)的連接參數(shù),如TCP源NAT時(shí),除了源地址必須要修改外,一般還要修改源端口,這個(gè)連接的后續(xù)包的源端口就都改這個(gè)端口值,而修改后的這個(gè)端口值必須是唯一的,和這個(gè)連接綁定,其他連接就不能再使用這個(gè)端口,如果找不到合適的tuple值,NAT將失敗,也就是說(shuō),對(duì)于多對(duì)一的NAT轉(zhuǎn)換,理論上最多只能處理65535個(gè)TCP連接,超過(guò)此數(shù)的新的TCP連接就無(wú)法進(jìn)行NAT了,對(duì)于TCP、UDP,(*unique_tuple)就是檢測(cè)查找一個(gè)新的未用端口生成一個(gè)新的tuple結(jié)構(gòu)對(duì)應(yīng)該連接,對(duì)應(yīng)ICMP,則是找一個(gè)未用的ID值,該函數(shù)在net/ipv4/netfilter/ip_nat_core.c的get_unique_tuple()函數(shù)中調(diào)用;

(*print):打印struct ip_conntrack_tuple中的協(xié)議相關(guān)信息;

(*print_range):打印struct ip_nat_range結(jié)構(gòu)中要進(jìn)行NAT修改的那部分協(xié)議信息;

最后,這些協(xié)議跟蹤結(jié)構(gòu)在net/ipv4/netfilter/ip_nat_core.c的ip_nat_init()函數(shù)中掛接到協(xié)議NAT鏈表中:
list_append(&protos, &ip_nat_protocol_tcp);
list_append(&protos, &ip_nat_protocol_udp);
list_append(&protos, &ip_nat_protocol_icmp);
對(duì)新IP協(xié)議的NAT模塊的添加和跟蹤模塊的添加類似。

5. 其他IP協(xié)議的跟蹤和NAT

下面討論其他IP協(xié)議如果要進(jìn)行跟蹤和NAT要處理哪些協(xié)議相關(guān)數(shù)據(jù):

SCTP:RFC2960,協(xié)議號(hào)132,和TCP非常類似,用源端口和目的端口來(lái)識(shí)別;
                 SCTP Common Header Format
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Source Port Number        |     Destination Port Number   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Verification Tag                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           Checksum                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

IGMP:RFC3376,協(xié)議號(hào)2,IGMP頭內(nèi)信息太少,沒(méi)有特殊數(shù)據(jù)供識(shí)別
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Type     | Max Resp Time |           Checksum            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Group Address                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

GRE:RFC1701,RFC2784,協(xié)議號(hào)47,使用KEY來(lái)作為修改數(shù)據(jù),ver和protocol作為識(shí)別用的固定數(shù)據(jù)

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|C|R|K|S|s|Recur|  Flags  | Ver |         Protocol Type         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Checksum (optional)      |       Offset (optional)       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Key (optional)                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Sequence Number (optional)                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Routing (optional)                    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|C|       Reserved0       | Ver |         Protocol Type         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Checksum (optional)      |       Reserved1 (Optional)    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

ESP:RFC4303,協(xié)議號(hào)50,只能用SPI來(lái)識(shí)別,SPI是SA的一部分,不過(guò)是不能修改的,因?yàn)镾PI是在IKE協(xié)商過(guò)程中確定的,兩邊都已經(jīng)預(yù)先知道,一旦修改了就匹配不到SA了

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|               Security Parameters Index (SPI)                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |                      Sequence Number                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Payload Data* (variable)                   |
|                                                               |
|                                                               |
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|               |     Padding (0-255 bytes)                     |
+-+-+-+-+-+-+-+-+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               |  Pad Length   | Next Header   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Integrity Check Value-ICV   (variable)                |
~                                                               ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

AH:RFC4304,協(xié)議號(hào)51,AH協(xié)議無(wú)法進(jìn)行NAT的,否則認(rèn)證就會(huì)失敗,跟蹤也只能靠SPI

6. 結(jié)論

netfilter的IP協(xié)議跟蹤和NAT處理很好地實(shí)現(xiàn)了模塊化,但除了netfilter自帶的模塊外,可處理其他IP協(xié)議也已經(jīng)不多了,只有GRE和SCTP可以新增模塊,其他協(xié)議增加模塊基本無(wú)意義。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Linux下NAT功能的實(shí)現(xiàn)
Netfilter框架
綠盟科技--www.nsfocus.com--綠盟月刊
洞悉linux下的Netfilter&iptables:網(wǎng)絡(luò)地址轉(zhuǎn)換原理之DNAT
Linux下如何實(shí)現(xiàn)網(wǎng)絡(luò)狀態(tài)檢測(cè)
TCP/IP學(xué)習(xí)(28)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服