Netfilter 是如何工做的(一):HOOK點

寫在前面

本系列不是介紹How to配置iptables的文章。由於網絡上已經有不少這類型的教程了,其中一些還不錯(好比連接).數組

本系列也不是通常意義上的Netfilter源碼分析文章。由於大段粘貼代碼也會讓人心生畏懼和厭煩!網絡

本系列文章的目標是,用盡可能少的文字和圖片講明白How Netfilter work框架

Netfilter 的基本概念

Netfilter是一套融入Linux內核網絡協議棧中的報文處理(過濾或者修改)框架。它在內核中報文的關鍵流動路徑上定義了5HOOK點(下圖藍色方框),各個協議(如IPv4IPv6ARP)能夠在這些HOOK點安裝鉤子函數,報文流經此地,內核會按照優先級調用這些鉤子函數,這些鉤子函數最終會決定報文是被NF_ACCEPT(放行)仍是NF_DROP(丟棄)。函數

forward-model

圖中紅色虛線表示內核最多見的報文流經的路徑:本機接收轉發本機發送
5HOOK點分別是:路由前本地上送轉發本地發送路由後1源碼分析

鏈(chain) & 表(table)

初次接觸iptables的同窗可能會被四表五鏈這個名字嚇到,特別是這個名字真的很容易使人困惑! 而當你瞭解了Netfilter的實現細節後,纔會發現:噢,原來就是HOOK點,HOOK點就是,由於有5HOOK點,因此有五鏈spa

那麼,爲何要叫呢?.net

由於一個HOOK點能夠上能夠安裝多個鉤子, 內核用「鏈條」將這些鉤子串起來!設計

圖片描述
相比之下,四表(table)就沒那麼神祕了: 起過濾做用的filter表、起NAT做用的nat表,用於修改報文的mangle表,用於取消鏈接跟蹤的raw表。code

Netfilter設計多個表的目的,一方面是方便分類管理,另外一方面,更重要的是爲了限定各個鉤子(或者說用戶規則)執行的順序!教程

PREROUTING這個HOOK點爲例,用戶使用iptables設置的NAT規則和mangle會分別掛到nat hookmangle hookNAT表的優先級天生比mangle表低,所以報文必定會先執行mangle表的規則。

圖片描述

這就是 四表五鏈 的概念。我我的認爲 的比 重要多了. 由於就算 Netfilter沒有表的概念,那麼經過當心翼翼地設置各個 rule的順序其實也能夠達到相同的效果。但 (也就是 HOOK點)的做用是獨一無二的。換個角度,用戶在配置 iptables規則時,更多的精力也是放在 "應該在哪一個HOOK點進行操做",至於用的是 filter表、 nat表仍是其餘表,其實都是瓜熟蒂落的事情。

Hook

HOOK 點的位置

用戶經過iptables配置的規則最終會記錄在HOOK點。HOOK點定義在struct net結構中,即HOOK點是各個net namespace中獨立的。因此,在使用容器的場景中,每一個容器的防火牆規則是獨立的。

struct net {
    /* code omitted */
    struct netns_nf        nf;
    /* code omitted */
}

struct netns_nf {
    /* code omitted */
    struct list_head hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
};

從上面的定義能夠看到,HOOK點是一個二維數組,每一個元素都是一個鏈表頭。它的第一個維度是協議類型,其中最經常使用的NFPROTO_IPV4,咱們使用的iptables命令都是將這個鉤子安裝到這個協議的hook,而使用ip6tables就是將鉤子安裝到NFPROTO_IPV6hook;第二個維度是,對於IPV4來講,它的取值範圍以下:

enum nf_inet_hooks{
    NF_INET_PRE_ROUTING,
    NF_INET_LOCAL_IN,
    NF_INET_FORWARD,
    NF_INET_LOCAL_OUT,
    NF_INET_POST_ROUTING,
    NF_INET_NUMHOOKS,
}

HOOK 點的元素

hooks的每一個元素都是鏈表頭,鏈表上掛的元素類型是struct nf_hook_ops,這些元素有兩個來源,一類來自於Netfilter初始化時各個表(如filter)的初始化,另外一類來自於如鏈接跟蹤這樣的內部模塊。下圖展現了第一類來源的元素的掛接狀況,它們按優先級排列(數字越小優先級越高),而.hook就是報文到達對應的路徑時會執行的鉤子函數。

圖片描述

附:相關內核函數的例子

iptable_filter_init 
  |--xt_hook_link
    |-- nf_register_hooks
       |-- nf_register_hook

HOOK 點的調用

Netfilter框架已經徹底融入內核協議棧了,因此在協議棧代碼中經常能夠看到NF_HOOK宏的調用,這個宏的參數指定了HOOK點。

以本機收到IPv4報文爲例

int ip_rcv(struct sk_buff* skb,...)
{
   // code omitted
   return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, net, NULL, skb, dev, NULL, ip_rcv_finish); 
   // code omitted
}

它指定要遍歷的鉤子函數是net namespacenethooks[NFPROTO_IPV4][NF_INET_PRE_ROUTING]鏈表上的元素,也就是上面圖中的第一行的鏈表。若是三個鉤子函數執行的結果(verdict)都是NF_ACCEPT,那麼NF_HOOK指定的ip_rcv_finish就會被執行。

相關文章
相關標籤/搜索