共计 1398 个字符,预计需要花费 4 分钟才能阅读完成。
每一条
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
包含的动作。
REF
netfilter-hacking-HOWTO