天天看點

Netfilter與FreeBSD的網絡包過濾

在Linux中,使用Netflter來進行包過濾,所有的邏輯都要挂接在Netfilter的某個或者某些HOOK點上,并且實作成該HOOK點上的一個或者多個hook函數,這在Netfilter架構中是用nf_hook_ops結構體來表示的,整個Netfilter的架構如下圖所示:

上圖中有一部分被稱為“過濾”子產品,這在Netfilter中是通過filter表來實作的,filter表被劃分為一條條的rule,被挂在FORWARD/INPUT/OUTPUT這三個HOOK點上,其nf_hook_ops結構體是:

其hook函數内部調用ipt_do_table來實作rule的周遊比對。

        前面幾篇文章提到了FreeBSD的Netgraph,它相比Netfilter更加獨立,因為它除了一個_p回調函數和标準協定棧相關之外,并不和協定棧有任何聯系。事實上,你将會發現,在FreeBSD的包過濾子產品中,Netgraph僅僅扮演了Netfilter的類似nf_hook_ops的概念,而不是Netfilter本身,那麼FreeBSD中誰來扮演Netfilter呢?答案是:沒有!你會發現,FreeBSD的協定棧都是通過單一的回調函數來被擴充的,包括包過濾也不例外的。回調函數可以最大限度的解除和标準協定棧的耦合。不像Netfilter,是Netfilter本身決定了各個hook函數按照什麼順序被調用,而Netfilter本身何時被調用是标準協定棧來決定的。從下圖展示的FreeBSD的協定棧擴充架構可見一斑。

可以看出,Netgraph可以直接挂在标準協定棧上,還可以被挂在另外的擴充子產品上,非常靈活(故而上圖中部分連接配接線使用更加柔和的曲線來畫出)。在代碼實作上,FreeBSD幾乎和Netfilter沒有任何差別,我們看一下ip_input函數:

pfil_run_hooks在這裡接管了一切,其作用很類似Netfilter的NF_HOOK。差别僅僅在于由于Netfilter是内嵌進标準協定棧的,是以隻要被Netfilter砍斷的函數都主動的分為了兩個階段:XXX以及XXX_finish,而FreeBSD并沒有這樣。FreeBSD的pfil也有Netfilter的nf_hook_ops的對應概念:

所謂的pfil_run_hooks函數其實就是周遊一個連結清單并調用每一個節點上的回調函數,該類連結清單在FreeBSD的協定棧中有好幾個,非常類似于Netfilter的HOOK點的概念,不同的連結清單hook執行不是按照事先定義好優先級的方式進行的。

        說到這,可能有點暈了,ipfw,ipf,netgraph的關系到底是什麼啊!實際上它們之間可以任意組合,這些子產品之間以及它們和标準協定棧之間可以進行任意你喜歡的組合方式,協定棧隻是在“某些固定”的地方設定了一些hook,不同于Netfilter,這些hook并沒有規定你必須做什麼和必須不能做什麼,并且這些hook點之間是互相獨立的,你可以直接使用netgraph,也可以将一張graph挂在一個filter上。正是這種靈活性使得FreeBSD成為了網絡定制的首選。

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1268978