本文檔的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/