close

一般在 Linux kernel 中看見的 Netfilter

主要是在 IPv4 封包所會經過的五大掛鉤點

分別是 PREROUTING、INPUT、FORWARD、OUTPUT 和 POSTROUTING

封包進來後會先通過 PREROUTING 這個掛鉤

接下來會進行查表的動作來判斷封包是要往上送給本機端還是要轉送

如果是要轉送就會通過 FORWARD 這個掛鉤

如果是要往上送給本機端的就會通過 INPUT 這個掛鉤

通過 FORWARD 的封包會再往下通過 POSTROUTING 後往外傳送

至於從本機端產生的封包會先查表確定要往哪裡傳送

然後分別通過 OUTPUT 和 POSTROUTING 這兩個掛鉤後往外傳送

以上看到的是封包在 Netfilter 運作大致的流向

 

 

 

那麼 Netfilter 這些掛鉤是如何實作出來的呢

要知道

Linux kernel 中很多資料結構是使用所謂的 doubly linked list 去串起來的

這些掛鉤也不例外

(以下 kernel 版本為 2.6.29)

 

 

 

首先要先指出在 Netfilter 掛鉤中有兩個資料結構要去維持

第一個是只有 list head 的 nf_hooks

另外一個是掛鉤本身真正存放資料的資料結構 nf_hook_ops

nf_hooks 他只是一個頭的作用

用來把 nf_hook_ops 以及指示說他是哪個 protocol family

怎麼說呢?

因為 nf_hooks 它是一個二維的陣列

他被宣告成

struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;

其中 NFPROTO_NUMPROTO 是 13,NF_MAX_HOOKS 是 8

所以如果 protocol family 是 IPv4,然後我這個掛鉤是 PREROUTING

那這個資料結構就會被放置在以 nf_hooks[NFPROTO_IPV4][NF_INET_PRE_ROUTING] 為首的 list 之下

嗯嗯

就是靠這種方式把這些 nf_hook_ops 給串起來

那麼安插在 list 中的順序靠的是 priority

priority 愈高,安插的位置就會愈前面

至於被放到 list 之前則是要做所謂的「註冊」和「註銷」的動作

透過 nf_register_hook() 或 nf_register_hooks() 把 nf_hook_ops 加到 list 裡面

透過 nf_unregister_hook() 或 nf_unregister_hooks() 把 nf_hook_ops 從 list 中刪除

 

 

 

以 ip_rcv() 來看

在其底部呼叫了 NF_HOOK() 這個巨集以調用掛鉤

其中最後一個參數為 okfn()

表示當封包通過此掛鉤後

會去叫用 okfn() 以做進一步的處理

此例為 ip_rcv_finish()

 

 

 

NF_HOOK() 這個巨集被定義為 NF_HOOK_THRESH()

但是 NF_HOOK_THRESH() 實際上被定義為一個回傳值

假設叫用 nf_hook_thresh() 所回傳的值為一(允許通過)

則 NF_HOOK_THRESH() 的回傳值將定義為 okfn() 的回傳值

那麼 nf_hook_thresh() 是做什麼用的呢?

它的目的其實就是要叫用 Netfilter 掛鉤

因此 nf_hook_thresh() 是一個重要的分界點

假設使用者沒有以 iptables 設定任何規則

表示掛鉤為空、不存在

封包自然而然就會被允許通過

一切很合理

假設使用者有以 iptables 中設定一些規則

那麼在 nf_hooks 的某一個元素就會有 nf_hook_ops 被串聯在該 list 之下

則 nf_hook_slow() 會被呼叫用來處理串聯該 list 的掛鉤

 

 

 

nf_hook_slow() 裡面有一個重要的函式稱做 nf_iterate()

它會一一地去處理該 list 中每個掛鉤

每次處理一個掛鉤

會有一個回傳值存在 verdict 這個變數當中

可能是 NF_ACCEPT 或 NF_STOP 表示接收

可能是 NF_DROP 表示丟棄

可能是 NF_QUEUE 表示這個封包是要直接丟給應用層的

那重點是 nf_iterate() 又做了什麼事

nf_iterate() 會去一一叫用定義在 nf_hook_ops 中的 hook 來處理

這是 Netfilter 它程式碼連續呼叫的最底層

至於 hook 是什麼東西就是 iptables 的範圍了

 

 

 

在 net/ipv4/netfilter/iptable_filter.c 即有宣告 filter TABLE 中的三個掛鉤點

該 nf_hook_ops 應該被給定什麼值

這是屬於 iptables 這邊的範疇而不是 Netfilter

因為這兩個是分開實作的

 

 

 

注意到這些 nf_hook_ops 中的 hook

最後都會去叫用到 ipt_do_table() 這個函式

該函式才是真正去處理規則比對的部分

也就是做 packet match 的動作

然後取出 target

看是要接收、丟棄還是其它的動作

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 fantasymew 的頭像
    fantasymew

    小孫的狂想世界

    fantasymew 發表在 痞客邦 留言(2) 人氣()