iptables 的各中mark

來源:互聯網
上載者:User
本文著重分析核心中CONNMARK的實現,同時還包括MARK的match和target模組的實現。因為CONNMARK模組通常是和MARK模組搭配使用的。關於iptables中如何使用這三個模組,參看本人的另外一篇文章《Netfilter CONNMARK用法及分析(一)-- iptables命令列的使用》。

本文歡迎自由轉載,但請標明出處和本文連結,並保持本文的完整性。
CU: Godbach
    Blog:http://blog.chinaunix.net/u/33048/index.html
Oct 31, 2009

1. CONNMARK及相關模組的選項
這裡先列出CONNMARK、MARK和mark模組的iptables命令列的選項,隨後我們再逐一分析各個模組的核心實現。iptables版本為v1.3.5。

(1)CONNMARK target的選項
選項        功能
--set-mark value[/mask]        給連結追蹤記錄打標記。
--save-mark [--mask mask]        將資料包上的標記值記錄到連結追蹤記錄上。
--restore-mark [--mask mask]        重新設定資料包的nfmark值。

(2)MARK target 的選項
選項        功能
--set-mark value        設定資料包的nfmark值。
--and-mark value        資料包的nfmark值和value進行按位與運算。
--or-mark  value        資料包的nfmark值和value進行按或與運算。

(3)MARK match的選項
選項        功能
[!] --mark value[/mask]        資料包的nfmark值與value進行匹配,其中mask的值為可選的。

其中CONNMARK和MARK match中都有mask選項,這個主要用來指定給出value值中哪幾位是需要設定的。通常,如果我們不指定mask的話,其值會被預設初始為0xFFFFFFFFUL。

2. MARK target的核心實現
我這裡分析的核心源碼版本是2.6.18,該模組的代碼見檔案xt_MARK.c,其核心的target實現代碼如下: 41 static unsigned int
42 target_v1(struct sk_buff **pskb,
43       const struct net_device *in,
44       const struct net_device *out,
45       unsigned int hooknum,
46       const struct xt_target *target,
47       const void *targinfo,
48       void *userinfo)
49 {
50     const struct xt_mark_target_info_v1 *markinfo = targinfo;
51     int mark = 0;
52 
53     switch (markinfo->mode) {
54     case XT_MARK_SET:
55         mark = markinfo->mark;
56         break;
57 
58     case XT_MARK_AND:
59         mark = (*pskb)->nfmark & markinfo->mark;
60         break;
61 
62     case XT_MARK_OR:
63         mark = (*pskb)->nfmark | markinfo->mark;
64         break;
65     }
66          /*將使用者佈建的mark值賦給資料包的nfmark*/
67     if((*pskb)->nfmark != mark)
68         (*pskb)->nfmark = mark;
69 
70     return XT_CONTINUE; 複製代碼 MARK target三個選項中最常用的應該是--set-mark,給資料包的nfmark設定標記。諸如下面這條規則
iptables -A POSTROUTING -p tcp --dport 21 -t mangle -j MARK --set-mark 1
就是將符合前面匹配選項的資料包的nfmark值設定為1。在核心中對應的源碼為: 54     case XT_MARK_SET:
55         mark = markinfo->mark;
56         break;
        選項--and-mark對應的源碼為:
58     case XT_MARK_AND:
59         mark = (*pskb)->nfmark & markinfo->mark;
60         break; 複製代碼 功能就是將資料包中記錄的nfmark值和使用者佈建的value進行按位與。同理選項--or-mark就是將資料包中記錄的nfmark值和使用者佈建的value進行按位或,其源碼如下: 62     case XT_MARK_OR:
63         mark = (*pskb)->nfmark | markinfo->mark;
64         break; 複製代碼 該模組最後統一判斷一下設定後的mark值是否與資料包中儲存的nfmark值相等,如果不等,則更新資料包的nfmark值為剛剛設定的mark。其代碼如下: 67     if((*pskb)->nfmark != mark)
68         (*pskb)->nfmark = mark; 複製代碼 個人覺得不管資料包nfmark和mark是否相等,直接將mark賦給nfmark就可以了。這裡加一條if判斷,難道是為了當兩個值相等的時候,少執行一次寫記憶體的指令?

3. MARK match的核心實現
該模組的實現在核心源碼的xt_mark.c中。其核心匹配模組的實現代碼如下: 22 static int
23 match(const struct sk_buff *skb,
24       const struct net_device *in,
25       const struct net_device *out,
26       const struct xt_match *match,
27       const void *matchinfo,
28       int offset,
29       unsigned int protoff,
30       int *hotdrop)
31 {
32     const struct xt_mark_info *info = matchinfo;
33 
34     return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
35 } 複製代碼 該模組實現的功能相對簡單,就是判斷一下資料包的nfmark值是否與使用者指定的相同。判斷的時候要考慮mask以及取反的標記位。
        下面這條iptables規則就是實現了對所有標記不為0的資料包都執行ACCEPT動作:
iptables -A POSTROUTING -t mangle -m mark ! --mark 0 -j ACCEPT
假設skb->nfmark為1,由於沒有指定mask,所以預設值為0xFFFFFFFFUL,info->mark為0,取反標記位被置位,info->invert為1。因此,((skb->nfmark & info->mask) == info->mark) ^ info->invert的結果應該是(1&0xFFFFFFFFUL)== 0)^1 = 0^1 = 1。
該模組match函數的傳回值為1,執行ACCEPT動作。

4. CONNMARK target的核心實現
該模組的實現在核心源碼的xt_CONNMARK.c中。其核心動作模組的實現代碼如下: 35 static unsigned int
36 target(struct sk_buff **pskb,
37        const struct net_device *in,
38        const struct net_device *out,
39        unsigned int hooknum,
40        const struct xt_target *target,
41        const void *targinfo,
42        void *userinfo)
43 {
44     const struct xt_connmark_target_info *markinfo = targinfo;
45     u_int32_t diff;
46     u_int32_t nfmark;
47     u_int32_t newmark;
48     u_int32_t ctinfo;
49     u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
50 
51     if (ctmark) {
52         switch(markinfo->mode) {
53         case XT_CONNMARK_SET:
54         newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
55         if (newmark != *ctmark)
56             *ctmark = newmark;
57         break;
58         case XT_CONNMARK_SAVE:
59         newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
60         if (*ctmark != newmark)
61             *ctmark = newmark;
62         break;
63         case XT_CONNMARK_RESTORE:
64         nfmark = (*pskb)->nfmark;
65         diff = (*ctmark ^ nfmark) & markinfo->mask;
66         if (diff != 0)
67             (*pskb)->nfmark = nfmark ^ diff;
68         break;
69         }
70     }
71 
72     return XT_CONTINUE;
73 } 複製代碼 這段代碼最開始先取出了資料包對應的連結跟蹤中記錄mark值的地址: 49     u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo); 複製代碼 然後判斷ctmark是否為NULL: 51     if (ctmark) { 複製代碼 如果ctmark == NULL,說明連結跟蹤中沒有ct->mark這個欄位,惟一可能的原因就是核心的設定檔中並沒有對CONFIG_NF_CONNTRACK_MARK進行配置,也就是沒有啟用Conntrack Mark的功能。否則,就根據使用者配置的動作進行相應的實現。
以下將分成三個部分介紹。

(1)給連結跟蹤設定標記(--set-mark)
        實現代碼如下: 53         case XT_CONNMARK_SET:
54         newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
55         if (newmark != *ctmark)
56             *ctmark = newmark;
57         break; 複製代碼 這裡先按照markinfo->mask中所有被置位的bit,將*ctmark中對應的bit位清零,然後再與markinfo->mark進行按位或。這樣就保證了mask中置位的bit位,一定為按照mark中的值重新設定。
        55~57行代碼的實現和我們第2部分分析的67~68代碼的實現相同。

(2)儲存標記值到連結跟蹤(--save-mark)
        實現代碼如下: 58         case XT_CONNMARK_SAVE:
59         newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
60         if (*ctmark != newmark)
61             *ctmark = newmark;
62         break; 複製代碼 這部分代碼中mask的功能和上面分析的相同。為了簡單化分析起見,我們假設使用者沒有指定mask,預設值為0xFFFFFFFFUL。這樣,59行的計算簡化為:
        newmark = (*pskb)->nfmark
再加上後兩行代碼: 60         if (*ctmark != newmark)
61             *ctmark = newmark; 複製代碼 具體的功能就很明確了,將當前資料包記錄的nfmark值記錄到連結跟蹤中的ct->mark中。
        那麼,按理說如果資料包的流程走到這部分代碼,應該就是資料包已經被打上標記了,也就是前面分析的MARK target中--set-mark進行的處理。因此,在下在iptables規則的時候,通常--set-mark的規則在前,--save-mark的規則在後。這就保證了資料包先被打上標記,然後再將資料包上的標記記錄到其對應的連結跟蹤上。以下幾條樣本規則就是按照這個流程進行的:
iptables -A POSTROUTING -m mark --ma

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.