免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4081 | 回复: 11
打印 上一主题 下一主题

[网络子系统] 求版主 指导,netfilter发包总是死机 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-06-15 15:11 |只看该作者 |倒序浏览
本帖最后由 ierent168 于 2014-06-15 22:22 编辑

我现在总体的思路是这样的,建立eth0与eth1的透明桥,然后通过netfilter将透明桥上的数据包发给第三个端口进行监控。现在主要的问题是,如下面程序红色部分所示,在钩子函数中我用return NF_ACCEPT;这样就会产生死机,也根据前人资料加了 dev_put(dev);但是还是死机。但是我要是用return NF_STOLEN,就不会死机了,但是这样的话就无法实现透明桥功能了,也就是eth0发送的数据包,在eth1端口没有了。请问 这样如何是好,用return NF_ACCEPT 为什么会死机 ,该如何修改呢?

#include <linux/init.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/socket.h>/*PF_INET*/
#include <linux/netfilter_ipv4.h>/*NF_IP_PRE_FIRST*/
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/inet.h> /*in_aton()*/
#include <net/ip.h>
#include <net/tcp.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/moduleparam.h>

#define ETHALEN 14

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lyh");
struct nf_hook_ops nfho;
unsigned int myhook_func(unsigned int hooknum,
                        struct sk_buff *__skb,
                        const struct net_device *in,
                        const struct net_device *out,
                        int (*okfn)(struct sk_buff *))
{
    struct sk_buff *skb;
    struct net_device *dev;
    struct iphdr *iph;
    int ret,tot_len;
    skb = __skb;
    if(skb == NULL)
        return NF_ACCEPT;
    iph = ip_hdr(skb);//将skb强制转换成ip结构体型
    if(iph == NULL)
        return NF_ACCEPT;
    tot_len = ntohs(iph->tot_len);
        dev = dev_get_by_name(&init_net,"eth8");
        skb->pkt_type = PACKET_OTHERHOST;//发给别人的帧(监听模式时会有这种帧)
        skb->dev = dev;
        skb_push(skb, ETHALEN);//将skb->data指向l2层,之后将数据包通过dev_queue_xmit()发出
        ret = dev_queue_xmit(skb);
        if(ret < 0)
                {
                    printk("dev_queue_xmit() error\n");
                    goto out;
                }
    dev_put(dev);
    return NF_ACCEPT;
out:
    dev_put(dev);
    //free(skb);
    return NF_DROP;
}


static struct nf_hook_ops nfho={
        .hook           = myhook_func,
        .owner          = THIS_MODULE,
        .pf             = PF_INET,
        .hooknum        = NF_IP_PRE_ROUTING,
        .priority       = NF_IP_PRI_FIRST,
};

static int __init myhook_init(void)//__init,表示告诉gcc把该函数放在init这个section;
{
        int ret;
    ret = nf_register_hook(&nfho);
        if(ret < 0)
        {
            printk("%s\n", "can't modify skb hook!");
            return ret;
        }
    return ret;
}
static void myhook_fini(void)
{
    nf_unregister_hook(&nfho);
}
module_init(myhook_init);
module_exit(myhook_fini);

论坛徽章:
0
2 [报告]
发表于 2014-06-15 16:15 |只看该作者
有没有人知道 啊

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
3 [报告]
发表于 2014-06-15 18:10 |只看该作者
呵呵,“本主题需向作者支付 40 可用积分 才能浏览”
今天周日,估计没人

论坛徽章:
0
4 [报告]
发表于 2014-06-15 22:23 |只看该作者
回复 3# humjb_1983   失误 啊 我以为是悬赏的呢


   

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
5 [报告]
发表于 2014-06-16 09:30 |只看该作者
回复 1# ierent168
用return NF_ACCEPT;这样就会产生死机,也根据前人资料加了 dev_put(dev);但是还是死机。但是我要是用return NF_STOLEN,就不会死机了,但是这样的话就无法实现透明桥功能了,也就是eth0发送的数据包,在eth1端口没有了。请问 这样如何是好,用return NF_ACCEPT 为什么会死机 ,该如何修改呢?


如果你用NF_ACCEPT,那么同一个数据包会走两次netfilter,会被kfree两次,当然会死机了。

如果你用NF_STOLEN,那么数据包就走一次,kfree一次,也就没有问题了。

既然是监控,那么应该skb_copy一份数据包,将copy的数据包重新放到队列里面,原来的数据包返回NF_ACCPET.

   

论坛徽章:
1
摩羯座
日期:2014-05-07 11:21:33
6 [报告]
发表于 2014-06-16 09:58 |只看该作者
回复 5# 瀚海书香


    请教版主一个问题,刚才我想到利用tcpdump那样的原理,但是我看了下代码为什么它用的是skb_clone而不是skb_copy呢?
在packet_rcv中有
                if (skb_shared(skb)) {
                struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
                if (nskb == NULL)
                        goto drop_n_acct;

                if (skb_head != skb->data) {
                        skb->data = skb_head;
                        skb->len = skb_len;
                }
                kfree_skb(skb);   这里为什么也要free一下呢
                skb = nskb;
        }

.......
__skb_queue_tail(&sk->sk_receive_queue, skb);

按道理也应验用skb_copy呀

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
7 [报告]
发表于 2014-06-16 10:29 |只看该作者
回复 6# wan3610425
请教版主一个问题,刚才我想到利用tcpdump那样的原理,但是我看了下代码为什么它用的是skb_clone而不是skb_copy呢?
在packet_rcv中有
                if (skb_shared(skb)) {
                struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
                if (nskb == NULL)
                        goto drop_n_acct;

                if (skb_head != skb->data) {
                        skb->data = skb_head;
                        skb->len = skb_len;
                }
                kfree_skb(skb);   这里为什么也要free一下呢
                skb = nskb;
        }

.......
__skb_queue_tail(&sk->sk_receive_queue, skb);

按道理也应验用skb_copy呀


第一个问题:为什么用skb_clone不用skb_copy?
    理论上来说,两个都是可以的。如果skb_clone只是负责sk_buff 结构体,skb_copy是sk_buff结构体和data部分。如果后续操作可能会修改data部分,需要用skb_copy;如果后续操作不会修改data部分,那么skb_clone就可以了。

第二个问题:为什么packet_rcv中需要kfree一下?
    pakcet_rcv作为一种protocol注册到ptype_all中。packet_rcv被调用的路径如下:   
    netif_receive_skb---->deliver_skb---->packet_rcv

     在deliver_skb中可以看到,内核将数据包递交给相应的协议处理函数是,会调用atomic_inc(&skb_users),也就是说让每个协议处理函数都handler了各自的数据包。那么协议处理函数在处理完成后,也要相应的atomic_dec(&skb_users),而kfree_skb其实就是atomic_dec的一个封装函数罢了。


   

论坛徽章:
0
8 [报告]
发表于 2014-06-16 21:26 |只看该作者
回复 5# 瀚海书香


    我用这个试过,skb_clone,还是不行,倒是不死机了,但是透明桥的另外一端还是没有数据,而且我现在出现了很奇怪的问题,假设A、B端口分别为透明桥的两端口,C端口设为监控端口:假如用anysend构造数据包在A端口发包,如果构造的数据包的目的MAC地址与要发往A端口的MAC地址相同,则透明桥另外一端口(B端口)就收不到数据包了,C端口可以收到数据包,但是如果构造的数据包的目的MAC地址与要发往A端口的MAC地址不相同,这B端口可以收到数据包,但是C端口也就是监控端口就收不到了。而且 我测试得出的结论是在netfilter我定义的钩子函数运行之前,内核会对数据包做一个验证,如果这个包的目的MAC地址事实不符合,那么就不会进入钩子函数执行,我测序打印就是这样的。但是不知道为什么 ,应该如何弄,原因的话 我 推测  就是在PRE_ROUTING进入钩子函数之前,内核会过滤,不知道有没有人知道是不是这么回事呢?

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
9 [报告]
发表于 2014-06-16 23:34 |只看该作者
回复 8# ierent168

返回 NF_STOLEN,且不调用 kfree_skb 仍然挂掉么


   

论坛徽章:
0
10 [报告]
发表于 2014-06-17 20:36 |只看该作者
回复 9# Godbach 不会的 ,要复制一个 才可以 ACCEPT呢



   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP