天天看點

2.6核心中netfilter hook點一覽

本文檔的Copyleft歸yfydz所有,使用GPL釋出,可以自由拷貝,轉載,轉載時請保持文檔的完整性,嚴禁用于任何商業用途。

msn: [email protected]

來源: http://yfydz.cublog.cn

1. 5個挂接點 以下核心代碼版本2.6.17.11。 1.1 PREROTING int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)

{

......

 return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,

         ip_rcv_finish);

......

}

1.2 INPUT int ip_local_deliver(struct sk_buff *skb)

{

......

 return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,

         ip_local_deliver_finish);

}

1.3 FORWARD int ip_forward(struct sk_buff *skb)

{

......

 return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev,

         ip_forward_finish);

......

}

1.4 OUTPUT

int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,

     u32 saddr, u32 daddr, struct ip_options *opt)

{

......

 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,

         dst_output);

} int ip_queue_xmit(struct sk_buff *skb, int ipfragok)

{

......

 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,

         dst_output);

......

} int ip_push_pending_frames(struct sock *sk)

{

......

 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,

        skb->dst->dev, dst_output);

......

} 1.5 POSTROUTING

int ip_output(struct sk_buff *skb)

{

 struct net_device *dev = skb->dst->dev;  IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);  skb->dev = dev;

 skb->protocol = htons(ETH_P_IP);  return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,

              ip_finish_output,

       !(IPCB(skb)->flags & IPSKB_REROUTED));

}

2. 每個挂接點所挂接的hook操作

隻考慮是AF_INET協定族的挂接點,以下各點的hook操作按執行順序排序,優先級數值越小,級别越高,執行順序越靠前。 如果使用者可以通過iptables規則進行控制的處理點稱為使用者可控,否則為不可控。

2.1 PREREOUTING

// 這個hook點隻丢棄skb結構中設定橋參數但沒有相關橋标志的包

// 使用者不可控

 { .hook = ip_sabotage_in,

   .owner = THIS_MODULE,

   .pf = PF_INET,

   .hooknum = NF_IP_PRE_ROUTING,

// 優先級最高

   .priority = NF_IP_PRI_FIRST,

        },

// 這個hook點完成分片重組,以後處理過程中的包都是非分片包

// 直到發送出去重新分片。注意2.6重組後的分片包并不進行線性

// 化,是以邏輯上應該連在一起的兩位元組資料可能分屬不同的頁,

// 存儲是不連續的

// 該點操作使用者不可控

 {

  .hook  = ip_conntrack_defrag,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_PRE_ROUTING,

// 優先級為-400

  .priority = NF_IP_PRI_CONNTRACK_DEFRAG,

 },

// 這個hook點為raw表,提供對收到的資料包在連接配接跟蹤前進行處理的手段

// 該點使用者可加載iptables規則進行控制

 {

  .hook = ipt_hook,

  .pf = PF_INET,

  .hooknum = NF_IP_PRE_ROUTING,

// 優先級為-300

  .priority = NF_IP_PRI_RAW,

  .owner = THIS_MODULE,

 },

// 這個hook點完成連接配接跟蹤,為每個skb找到所屬連接配接(ESTABLISHED, REPLY)

// 或建立連接配接(NEW, RELATED)

// 該點操作使用者不可控

 {

  .hook  = ip_conntrack_in,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_PRE_ROUTING,

// 優先級為-200

  .priority = NF_IP_PRI_CONNTRACK,

 },

// 這個hook點為mangle表,提供對收到的資料包進行修改的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_route_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_PRE_ROUTING,

// 優先級為-150

  .priority = NF_IP_PRI_MANGLE,

 },  

// 該hook點對剛收到本機的skb包進行目的NAT操作

// 使用者規則可控,nat表,但規則隻對NEW包進行處理,後續包自動處理

 {

  .hook  = ip_nat_in,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_PRE_ROUTING,

// 優先級為-100

  .priority = NF_IP_PRI_NAT_DST,

 },

// 該hook點對j進入本機的skb包進行排隊處理,QoS操作

// 使用者不可控

static struct nf_hook_ops ing_ops = {

 .hook           = ing_hook,

 .owner  = THIS_MODULE,

 .pf             = PF_INET,

 .hooknum        = NF_IP_PRE_ROUTING,

// 優先級為1

 .priority       = NF_IP_PRI_FILTER + 1,

};   2.2 INPUT

// 這個hook點為mangle表,提供對收到的資料包進行修改的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_route_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_IN,

// 優先級為-150

  .priority = NF_IP_PRI_MANGLE,

 },

// 這個hook點為filter表,提供對進入本機的資料包進行過濾的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_IN,

// 優先級為0

  .priority = NF_IP_PRI_FILTER,

 },

// 對進入本機的skb包進行源NAT操作

// 使用者規則可控,nat表,但規則隻對NEW包進行處理,後續包自動處理

 {

  .hook  = ip_nat_fn,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_IN,

// 優先級為100

  .priority = NF_IP_PRI_NAT_SRC,

 },

// 該hook點對進入本機的skb包均衡配置設定

// 使用者不可控

static struct nf_hook_ops ip_vs_in_ops = {

 .hook  = ip_vs_in,

 .owner  = THIS_MODULE,

 .pf  = PF_INET,

 .hooknum        = NF_IP_LOCAL_IN,

 .priority       = 100,

};

// 該hook點對進入本機的skb包完成對連接配接跟蹤的help,也就是

// 多連接配接協定中對子連接配接的處理

// 使用者不可控

 {

  .hook  = ip_conntrack_help,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_IN,

// 優先級為INT_MAX-2,相當低

  .priority = NF_IP_PRI_CONNTRACK_HELPER,

 },

// 對進入本機的skb包進行TCP序列号調整操作,主要是因為跟蹤多連接配接協定時

// 修改了資料包内容可能導緻資料包長度發生變化,相應序列号和确認号需要

// 自動調整

// 使用者規則不可控

 {

  .hook  = ip_nat_adjust,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_IN,

// 優先級為INR_MAX-1,相當低

  .priority = NF_IP_PRI_NAT_SEQ_ADJUST,

 },  

// 該hook點對進入本機的skb包完成最後的确認,隻對NEW包處理

// 确認NEW的連接配接資訊在目前的連接配接表中是不存在的

// 使用者不可控

 {

  .hook  = ip_confirm,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_IN,

// 優先級為INT_MAX,最低

  .priority = NF_IP_PRI_CONNTRACK_CONFIRM,

 },

2.3 FORWARD

// 這個hook點對由橋網卡轉發的skb包設定橋資訊和實體網卡等資訊

// 該函數可能會傳回NF_STOP不進行後續hook點的處理

// 使用者不可控

 { .hook = ip_sabotage_out,

   .owner = THIS_MODULE,

   .pf = PF_INET,

   .hooknum = NF_IP_FORWARD,

// 優先級為-175

   .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD,

        },

// 這個hook點為mangle表,提供對收到的資料包進行修改的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_route_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_FORWARD,

// 優先級為-150

  .priority = NF_IP_PRI_MANGLE,

 },

// 這個hook點為filter表,提供對轉發的資料包進行過濾的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_FORWARD,

// 優先級為0

  .priority = NF_IP_PRI_FILTER,

 },

// 該hook點對轉發的skb包均衡配置設定前處理ICMP異常

// 使用者不可控

static struct nf_hook_ops ip_vs_forward_icmp_ops = {

 .hook  = ip_vs_forward_icmp,

 .owner  = THIS_MODULE,

 .pf  = PF_INET,

 .hooknum        = NF_IP_FORWARD,

 .priority       = 99,

};

// 該hook點對轉發的skb包均衡配置設定

// 使用者不可控

static struct nf_hook_ops ip_vs_out_ops = {

 .hook  = ip_vs_out,

 .owner  = THIS_MODULE,

 .pf  = PF_INET,

 .hooknum        = NF_IP_FORWARD,

 .priority       = 100,

};   3.4 OUTPUT

// 這個hook點對自身發出的包完成分片重組,以後處理過程中的包都是非分片包

// 直到最後發送出去重新分片。注意2.6重組後的分片包并不進行線性

// 化,是以邏輯上應該連在一起的兩位元組資料可能分屬不同的頁,

// 存儲是不連續的

// 該點操作使用者不可控

 {

  .hook  = ip_conntrack_defrag,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_OUT,

// 優先級為-400

  .priority = NF_IP_PRI_CONNTRACK_DEFRAG,

 },

// 這個hook點為raw表,提供對本機發出資料包在連接配接跟蹤前進行處理的手段

// 該點使用者可加載iptables規則進行控制

 {

  .hook = ipt_hook,

  .pf = PF_INET,

  .hooknum = NF_IP_LOCAL_OUT,

// 優先級為-300

  .priority = NF_IP_PRI_RAW,

  .owner = THIS_MODULE,

 },

// 這個hook點對自身發出的包完成連接配接跟蹤,為每個skb找到所屬連接配接

// (ESTABLISHED, REPLY)或建立連接配接(NEW, RELATED)

// 該點操作使用者不可控

 {

  .hook  = ip_conntrack_local,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_OUT,

// 優先級為-200

  .priority = NF_IP_PRI_CONNTRACK,

 },

// 這個hook點為mangle表,提供對收到的資料包進行修改的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_local_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_OUT,

// 優先級為-150

  .priority = NF_IP_PRI_MANGLE,

 },  

// 對本機發出的skb包進行目的NAT操作

// 使用者規則可控,nat表,但規則隻對NEW包進行處理,後續包自動處理

 {

  .hook  = ip_nat_local_fn,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_OUT,

// 優先級為-100

  .priority = NF_IP_PRI_NAT_DST,

 },

// 這個hook點對由橋網卡發出的skb包設定橋資訊和實體網卡等資訊

// 該函數會傳回NF_STOP,提前終止檢查而傳回

// 使用者不可控

 { .hook = ip_sabotage_out,

   .owner = THIS_MODULE,

   .pf = PF_INET,

   .hooknum = NF_IP_LOCAL_OUT,

// 優先級為-50

   .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT,

         },

// 這個hook點為filter表,提供對本機發出的資料包進行過濾的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_local_out_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_LOCAL_OUT,

// 優先級為0

  .priority = NF_IP_PRI_FILTER,

 },  

2.5 POSTROUTING

// 這個hook點對由橋網卡發出的skb包設定橋資訊和實體網卡等資訊

// 該函數會傳回NF_STOP,提前終止檢查而傳回

// 使用者不可控

 { .hook = ip_sabotage_out,

   .owner = THIS_MODULE,

   .pf = PF_INET,

   .hooknum = NF_IP_POST_ROUTING,

// 優先級最高

   .priority = NF_IP_PRI_FIRST, },

// 這個hook點為mangle表,提供對收到的資料包進行修改的處理

// 該點使用者可加載iptables規則進行控制

 {

  .hook  = ipt_route_hook,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_POST_ROUTING,

// 優先級為-150

  .priority = NF_IP_PRI_MANGLE,

 },

// 該hook點對IPVS本身的控制包直接傳回NF_STOP不進行後續hook點處理

// 使用者不可控

static struct nf_hook_ops ip_vs_post_routing_ops = {

 .hook  = ip_vs_post_routing,

 .owner  = THIS_MODULE,

 .pf  = PF_INET,

 .hooknum        = NF_IP_POST_ROUTING,

// 優先級為99

 .priority       = NF_IP_PRI_NAT_SRC-1,

};

// 對本機發出的skb包進行源NAT操作

// 使用者規則可控,nat表,但規則隻對NEW包進行處理,後續包自動處理

 {

  .hook  = ip_nat_out,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_POST_ROUTING,

// 優先級為100

  .priority = NF_IP_PRI_NAT_SRC,

 },

// 該hook點對轉發的skb包完成對連接配接跟蹤的help,也就是

// 多連接配接協定中對子連接配接的處理

// 使用者不可控

 {

  .hook  = ip_conntrack_help,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

// 優先級為INT_MAX-2,相當低

  .hooknum = NF_IP_POST_ROUTING,

  .priority = NF_IP_PRI_CONNTRACK_HELPER,

 },

// 對發出本機的skb包進行TCP序列号調整操作,主要是因為跟蹤多連接配接協定時

// 修改了資料包内容可能導緻資料包長度發生變化,相應序列号和确認号需要

// 自動調整

// 使用者規則不可控

 {

  .hook  = ip_nat_adjust,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_POST_ROUTING,

// 優先級為INR_MAX-1,相當低

  .priority = NF_IP_PRI_NAT_SEQ_ADJUST,

 },

// 該hook點對進入本機的skb包完成最後的确認,隻對NEW包處理

// 确認NEW的新連接配接資訊在目前的連接配接表中是不存在的

// 使用者不可控

 {

  .hook  = ip_confirm,

  .owner  = THIS_MODULE,

  .pf  = PF_INET,

  .hooknum = NF_IP_POST_ROUTING,

// 優先級為INT_MAX,最低

  .priority = NF_IP_PRI_CONNTRACK_CONFIRM,

 },

3. 結論

由此可見,即使核心不支援bridge, ipvs和sched,一個轉發包通過netfilter時也會經過12個處理點的處理,任何一點的拒絕都會使該包丢棄,在各點的控制處理功能可以高度集中,象流水線的各個環節一樣。如果能用多核處理器能讓比較費資源的點單獨跑一個核,各個核的處理結果進行流水線,系統效率的提升肯定會很高,可惜這種AMP處理還是"Mission impossible",目前的SMP處理方式隻會使netfilter架構效率很低,什麼時候可以把“im”去掉還要等待。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22214587/viewspace-709503/,如需轉載,請注明出處,否則将追究法律責任。

轉載于:http://blog.itpub.net/22214587/viewspace-709503/

繼續閱讀