Linux Netfilter filter表注册

Linux Netfilter的filter表注册在以下几个链的位置:LOCAL_IN、FORWORD、LOCAL_OUT。
注册函数如下:

static int __init iptable_filter_init(void)
{
	int ret;

	if (forward < 0 || forward > NF_MAX_VERDICT) {
		printk("iptables forward must be 0 or 1\n");
		return -EINVAL;
	}

	/* Entry 1 is the FORWARD hook */
	initial_table.entries[1].target.verdict = -forward - 1;

    /* 通过iptable_filter_net_init函数调用ipt_register_table函数注册filter表net->ipv4.iptable_filter */
	ret = register_pernet_subsys(&iptable_filter_net_ops);
	if (ret < 0)
		return ret;

	/* Register hooks */
	/* 注册filter表 */
	ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
	if (ret < 0)
		goto cleanup_table;

	return ret;

 cleanup_table:
	unregister_pernet_subsys(&iptable_filter_net_ops);
	return ret;
}

filter表的hook定义,注册到三个链:

static struct nf_hook_ops ipt_ops[] __read_mostly = {
	{
		.hook		= ipt_local_in_hook,
		.owner		= THIS_MODULE,
		.pf		= PF_INET,
		.hooknum	= NF_INET_LOCAL_IN,
		.priority	= NF_IP_PRI_FILTER,
	},
	{
		.hook		= ipt_hook,
		.owner		= THIS_MODULE,
		.pf		= PF_INET,
		.hooknum	= NF_INET_FORWARD,
		.priority	= NF_IP_PRI_FILTER,
	},
	{
		.hook		= ipt_local_out_hook,
		.owner		= THIS_MODULE,
		.pf		= PF_INET,
		.hooknum	= NF_INET_LOCAL_OUT,
		.priority	= NF_IP_PRI_FILTER,
	},
};

LOCAL_IN的hook函数:

/* The work comes in here from netfilter.c. */
static unsigned int ipt_local_in_hook(unsigned int hook,
        struct sk_buff *skb,
        const struct net_device *in,
        const struct net_device *out,
        int (*okfn)(struct sk_buff *))
{
    /* 实现对报文的过滤,遍历filter表的所有规则,
     * 对数据包进行检查,然后根据返回值作后续动作 */
    return ipt_do_table(skb, hook, in, out,
            dev_net(in)->ipv4.iptable_filter);
}

FORWORD的hook函数:

static unsigned int ipt_hook(unsigned int hook,
        struct sk_buff *skb,
        const struct net_device *in,
        const struct net_device *out,
        int (*okfn)(struct sk_buff *))
{
    /* 实现对报文的过滤 */
    return ipt_do_table(skb, hook, in, out,
            dev_net(in)->ipv4.iptable_filter);
}

LOCAL_OUT的hook函数:
增加对数据包长度的判断,如果ip报头不完整,则返回NF_ACCEPT,不进行filter过滤。

static unsigned int ipt_local_out_hook(unsigned int hook,
        struct sk_buff *skb,
        const struct net_device *in,
        const struct net_device *out,
        int (*okfn)(struct sk_buff *))
{
    /* root is playing with raw sockets. */
    if (skb->len < sizeof(struct iphdr) ||
            ip_hdrlen(skb) < sizeof(struct iphdr))
        return NF_ACCEPT;

    return ipt_do_table(skb, hook, in, out,
            dev_net(out)->ipv4.iptable_filter);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值