Netfilter作为第三方源码拥有自己的网站http://www.netfilter.org/,确实比较牛逼。
尤其是应用层iptables作为工具对构建linux防火墙进行发挥特别大的作用。
Linux下通过nf_register_hooks对钩子函数进行注册,通过source insight对源码进行查看,
发现这么多地方调用了函数。
static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
{
.hook = ipv4_conntrack_in,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK,
},
{
.hook = ipv4_conntrack_local,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK,
},
{
.hook = ipv4_confirm,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
},
{
.hook = ipv4_confirm,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_CONNTRACK_CONFIRM,
},
}
static struct nf_hook_ops ipv4_defrag_ops[] = {
{
.hook = ipv4_conntrack_defrag,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
},
{
.hook = ipv4_conntrack_defrag,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,
},
}
static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
{
.hook = nf_nat_in,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_NAT_DST,
},
{
.hook = nf_nat_out,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SRC,
},
{
.hook = nf_nat_local_fn,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_NAT_DST,
},
{
.hook = nf_nat_fn,
.owner = THIS_MODULE,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC,
},
}
#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
(1 << NF_INET_FORWARD) | \
(1 << NF_INET_LOCAL_OUT))
static const struct xt_table packet_filter = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
.me = THIS_MODULE,
.af = NFPROTO_IPV4,
.priority = NF_IP_PRI_FILTER,
}
#define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \
(1 << NF_INET_LOCAL_IN) | \
(1 << NF_INET_FORWARD) | \
(1 << NF_INET_LOCAL_OUT) | \
(1 << NF_INET_POST_ROUTING))
static const struct xt_table packet_mangler = {
.name = "mangle",
.valid_hooks = MANGLE_VALID_HOOKS,
.me = THIS_MODULE,
.af = NFPROTO_IPV4,
.priority = NF_IP_PRI_MANGLE,
}
#define NAT_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \
(1 << NF_INET_POST_ROUTING) | \
(1 << NF_INET_LOCAL_OUT) | \
(1 << NF_INET_LOCAL_IN))
static const struct xt_table nat_table = {
.name = "nat",
.valid_hooks = NAT_VALID_HOOKS,
.me = THIS_MODULE,
.af = NFPROTO_IPV4,
}
其中filter,mangle 表通过xt_hook_link间接调用了 nf_register_hook,
分别注册了回调 iptable_filter_hook和iptable_mangle_hook 。
倒是nat表没有像 filter,mangle采用这种方式,而是
nf_nat_ops 这些回调函数与nat表产生了千丝万缕的关系。
通过一番priority的比较,最终总结出了各个钩子函数的调戏skb的关系图,
PRE_ROUTING
ipv4_conntrack_defrag(NF_IP_PRI_CONNTRACK_DEFRAG)
ipv4_conntrack_in(NF_IP_PRI_CONNTRACK)
iptable_mangle_hook(NF_IP_PRI_MANGLE)
nf_nat_in(NF_IP_PRI_NAT_DST)
FORWARD
iptable_mangle_hook(NF_IP_PRI_MANGLE)
iptable_filter_hook(NF_IP_PRI_FILTER)
LOCAL_IN
iptable_mangle_hook(NF_IP_PRI_MANGLE)
ipv4_conntrack_defrag(NF_IP_PRI_CONNTRACK_DEFRAG)
nf_nat_fn(NF_IP_PRI_NAT_SRC)
iptable_filter_hook(NF_IP_PRI_FILTER)
ipv4_confirm(NF_IP_PRI_CONNTRACK_CONFIRM)
LOCAL_OUT
ipv4_conntrack_local(NF_IP_PRI_CONNTRACK)
iptable_mangle_hook(NF_IP_PRI_MANGLE)
nf_nat_local_fn(NF_IP_PRI_NAT_DST)
iptable_filter_hook(NF_IP_PRI_FILTER)
POST_ROUTING
iptable_mangle_hook(NF_IP_PRI_MANGLE)
nf_nat_out(NF_IP_PRI_NAT_SRC)
ipv4_confirm(NF_IP_PRI_CONNTRACK_CONFIRM)