Netfilter/iptables是Linux內核內置的報文過濾框架,程序能夠經過該框架完成報文過濾、地址轉換(NAT)以及鏈接跟蹤等功能。html
Netfilter/iptables由兩部分組成,一部分是Netfilter的"鉤子(hook)",這些"鉤子"由Linux內核協議棧提供,內核模塊能夠經過註冊"鉤子"來完成各類各樣的功能。 另外一部分是iptables的規則,這些規則規定了"鉤子"如何工做。linux
下圖很直觀的說明了用戶空間的iptables和內核空間的ip_tables模塊、Netfilter之間的關係。數組
Netfilter是嵌入Linux內核協議棧的,設置在報文處理路徑上的一系列調用入口。 Netfilter一共有5個"鉤子"設置在IP協議棧的報文處理路徑上,這5個"鉤子"就是內嵌在內核協議棧的檢查點。 咱們能夠把處理函數註冊到各個檢查點,當報文通過各個檢查點時,就能夠經過"鉤子"函數對報文進行處理完成相應功能。框架
下圖說明了5個"鉤子"在內核協議棧的位置。 函數
在內核中,"鉤子"函數由一個全局二維數組nf_hooks按照協議族歸類存儲,在每一個協議族中,根據鉤子點順序排列,在鉤子點內則根據鉤子函數的優先級排列。 例如ipv4和ipv6就是兩個協議族,每一個協議族都包含5個"鉤子",每一個"鉤子"下面保存了註冊在這個"鉤子"上的函數地址。 學習
Netfilter定義了每一個鉤子函數的返回值,每一個鉤子函數只能返回下面的返回值,而不能自定義返回值。.net
"鉤子"的使用首先實例化一個nf_hook_ops對象,而後對其進行必要的初始化設置,最後經過nf_register_hook()函數將其註冊到二維數組nf_hooks中。 咱們首先初始化nf_hook_ops中的經常使用字段:unix
<!-- lang: c --> static struct nf_hook_ops nf_hook_test_ops = { .hook = test_hook_func; .hooknum = NF_INET_PRE_ROUTING; .pf = PF_INET; .owner = THIS_MODULE; .priority = NF_IP_PRI_FIRST; }
其中:code
而後在模塊加載和退出函數中註冊和移除鉤子函數:htm
<!-- lang: c --> int init_module(void) { nf_register_hook(&nf_hook_test_ops); } void cleanup_module() { nf_unregister_hook(&nf_hook_test_ops); }
下面是回調函數的聲明:
<!-- lang: c --> static unsigned int test_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff*)
從上述過程能夠看出,鉤子函數的使用與iptables沒有任何關係,也就是說若是某個模塊須要對協議棧的報文進行處理,但不須要用戶空間的參數,那麼徹底能夠只註冊鉤子函數,而不須要編寫iptables的模塊。
即便須要用戶空間的參數,也能夠經過proc或者netlink等其餘用戶態和內核態通訊方式來傳遞參數,這樣就能夠更靈活的使用Netfilter了。