每一條iptables
配置的rule
都包含了匹配條件(match
)部分和動作(target
)。當報文途徑HOOK
點時,Netfilter
會逐個遍歷掛在該鉤子點上的表的rule
,若報文滿足rule
的匹配條件,內核就會執行動作(target
)。
擴展match的表示
而match
又可以分爲標準match
和擴展match
兩部分,其中前者有且只有一個,而後者有零到多個。在Netfilter
中,標準match
條件用ipt_entry
表示(這個在上一篇文章中已經說過了),其中包括源地址和目的地址等基本信息,而擴展match
用ipt_entry_match
表示:
這個結構上面是一個union
,下面是一個柔性數組。union
的元素有三個,拋開最後一個用於對齊的match_size
,前兩個元素表示它在用戶空間和內核空間的有不同的解釋(這個結構在linux
內核代碼和iptables
應用程序代碼中定義一樣)
什麼意思呢? 還是以本文開頭的那條rule
爲例,這條rule
使用了tcp
擴展模塊,匹配條件爲--dport 80
,所以用戶態的iptables
程序會這樣理解這個結構:
當內核收到這條rule
時,會根據名字"tcp"去從Netfilter
框架中"搜索"已註冊的擴展match
,若找到,就設置其match
指針.這樣,從內核Netfilter
的角度來看,擴展匹配條件就變成了這樣:
註冊擴展 match
我們需要將擴展match
預先註冊到Netfilter
框架中,才能在之後的配置中使用這個匹配條件。就拿本文最初的那條規則來說,需要一個隱含的前提就是tcp這個xt_match
事先被註冊到Netfilter
框架了。這部分工作是在xt_tcpudp.c
定義的內核模塊中完成的。
除了tcp
, 通過xt_register_match
接口,其他各個模塊都可以註冊自己的擴展匹配條件。
每個xt_match
有三個函數指針,其中
match
:這個函數指針會在擴展匹配報文時被調用,用來判斷skb
是否滿足條件,如果滿足則返回非0值。checkentry
:這個函數在用戶配置規則時被調用,如果返回0,表示配置失敗。destroy
:這個函數再使用該match
的規則被刪除時調用。
使用擴展match
當數據包真的到達時,Netfilter
會調用各個表安裝的鉤子函數,這些鉤子函數用表中的每條rule
去嘗試匹配數據包