每一條iptables
配置的規則(rule
)都包含了匹配條件(match
)部分和動作(target
)。當報文途徑HOOK
點時,Netfilter
會逐個遍歷掛在該鉤子點上的表的rule
,若報文滿足rule
的匹配條件,內核就會執行動作(target
)。
上面是一條普通iptables
規則,如果報文匹配前面的條件,就會執行最後的-j DROP
,它就是這條規則的動作(target
)
普通動作 & 擴展動作
動作又可分爲普通target和擴展target兩類,其中普通動作是指ACCEPT
(允許報文通過)、DROP
(拒絕報文通過)這類簡單明瞭的行爲,而擴展target
是指包含了其他操作的動作,比如REJECT
動作會產生ICMP
差錯信息、LOG
動作記錄日誌、SNAT
和DNAT
用於進行地址轉換。
本文不涉及 How to
配置這些動作的規則,也不涉及這些動作各自的作用是什麼,對此有興趣的讀者可以參考鏈接
表示 target
Netfilter
使用xt_standard_target
表示一個動作:
該結構由兩部分組成,其中verdict
是動作的編碼, 取值有NF_DROP
、NF_ACCEPT
、NF_QUEUE
等等。對於普通動作來說,有verdict
就夠了,但對於擴展動作來說,還需要有地方存儲額外的信息(eg. 如何進行NAT
),這裏的target
就是存儲這些額外信息的地方。與本系列上一篇中說的xt_entry_match
一樣,xt_entry_target
結構同樣是一個union
。它們的設計思路是一樣的:內核代碼和iptables
用戶態代碼定義這樣一個同樣的數據類型,用戶態使用的是user
部分,設置要使用的擴展動作的name
(普通動作的name
爲""),內核收到該結構後,根據name
查詢到註冊過的動作,將該信息掛到xt_entry_target
的target
指針上。而data
字段表示的柔性數組區域就是各種擴展模塊各顯神通的地方了,對NAT
來說,這裏存儲轉換後的地址。
註冊 target
我們需要將target
預先註冊到Netfilter
框架中,才能在之後的配置中使用這個target
。就拿本文最初的那條規則來說,需要一個隱含的前提就是SNAT
這個xt_target
事先被註冊到Netfilter
框架了。這部分工作在xt_nat.c
定義的內核模塊中完成:
除了SNAT
, 通過xt_register_target
接口,其他各個模塊都可以註冊自己的動作。根據名字進行區分,所有的target
會掛到xf
鏈表上。
每個target
上有三個函數指針,其中
-
target
:這個函數將決定skb
的後續處理結果,如果爲NULL
,那麼這條規則的動作就是普通target
,處理結果從外面的verdict
就可以得出。如果不爲NULL
,那麼就執行這個函數,這個函數返回NF_DROP
,NF_ACCEPT
,NF_STOLEN
這類動作 -
checkentry
:這個函數在用戶配置規則時被調用,如果返回0,表示配置失敗。 -
destroy
:這個函數再使用該target
的規則被刪除時調用。
查找 target
當用戶通過iptables
下發一條規則時,Netfilter
會從xf
鏈表上查找是否已有這樣的target
執行 target
當數據包經過HOOK
點,如果某條rule
的匹配條件與報文一致,就會執行該rule
包含的動作。