免费注册 查看新帖 |

Chinaunix

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

[C] 请教一个netfilter的问题!!毕业设计!!急!!谢谢各位大哥了!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-01 23:05 |只看该作者 |倒序浏览
想实现一个拦截并可以修改http报文的程序,搭建了一个透明网桥,在netfilter里将目的IP修改成本机,用户态程序监听处理,目前netfilter那部分内核模块总是死机,同样的代码在不同的地方,一个成功一个失败,不知道什么原因

先说一下网络拓扑:【192.168.1.1】----【中间设备linux】----【192.168.1.2】
本机使用brctl搭建透明网桥,地址192.168.1.111,本机有一个进程监听80端口,流程如下:
(1)    192.168.1.2的主机发出SYN,源地址192.168.1.2,目的地址为192.168.1.1
(2)    中间设备在NF_IP_PRE_ROUTING处拦截,修改目的IP为192.168.1.111
(3)    协议栈处理完,交给用户态程序,发出SYN/ACK,源地址192.168.1.2,目的地址为192.168.1.111
(4)    在NF_IP_LOCAL_OUT处拦截,修改源IP为192.168.1.1
(5)    192.168.1.2接到SYN/ACK,发送ACK


代码如下:
static struct nf_hook_ops nfho_in;
static struct nf_hook_ops nfho_out;

unsigned int hook_func_in(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 *sb = *skb;

        struct tcphdr *tcp_buff = NULL;
        unsigned char *http_buff = NULL;

        int tcp_len = 0;
        int http_len = 0;

/*******************************************************************************************************/       
// 除80端口的都放行       
        if (*((u_short *)(sb->mac.raw + 12)) != 0x0008)
                return NF_ACCEPT;
        if (sb->nh.iph->protocol != IPPROTO_TCP)
                return NF_ACCEPT;
        tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
        if (tcp_buff->source != 0x5000 && tcp_buff->dest != 0x5000)       
                return NF_ACCEPT;

        sb = skb_copy(sb, 1);
        *skb = sb;       

        tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
        http_buff = (unsigned char *)tcp_buff + tcp_buff->doff * 4;

/*******************************************************************************************************/
// 修改目的IP指向自己

        if (tcp_buff->dest == 0x5000)       
                sb->nh.iph->daddr = 0x6f01a8c0;
/******************************************************************************************************/

// 修复校验值
        // fix sk_buff checksum                       
        tcp_len = ntohs(sb->nh.iph->tot_len) - sb->nh.iph->ihl * 4;
        http_len = tcp_len - tcp_buff->doff * 4;
        sb->csum = 0;
        sb->csum = csum_partial((unsigned char *)http_buff, http_len, 0);
        // fix tcp checksum
        tcp_buff->check = 0;
tcp_buff->check = csum_tcpudp_magic(sb->nh.iph->saddr,sb->nh.iph->daddr, tcp_len, IPPROTO_TCP, csum_partial((unsignedchar *)tcp_buff, tcp_buff->doff * 4, sb->csum));
        // fix ip checksum
        sb->nh.iph->check = 0;
        sb->nh.iph->check = ip_fast_csum((unsigned char *)sb->nh.iph, sb->nh.iph->ihl);
        return NF_ACCEPT;
}

unsigned int hook_func_out(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 *sb = *skb;

        struct tcphdr *tcp_buff = NULL;
        unsigned char *http_buff = NULL;

        int tcp_len = 0;
        int http_len = 0;

/*******************************************************************************************************/       
        printk("data out\n");
        if (*((u_short *)(sb->mac.raw + 12)) != 0x0008)
                return NF_ACCEPT;
        if (sb->nh.iph->protocol != IPPROTO_TCP)
                return NF_ACCEPT;
        tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
        if (tcp_buff->source != 0x5000 && tcp_buff->dest != 0x5000)       
                return NF_ACCEPT;

//return NF_ACCEPT;       

// 执行到下面就死机了

        sb = skb_copy(sb, 1);
        *skb = sb;       

        tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
        http_buff = (unsigned char *)tcp_buff + tcp_buff->doff * 4;

/*******************************************************************************************************/
        if (tcp_buff->dest == 0x5000)       
                sb->nh.iph->saddr = 0x0101a8c0;
/******************************************************************************************************/

        // fix sk_buff checksum                       
        tcp_len = ntohs(sb->nh.iph->tot_len) - sb->nh.iph->ihl * 4;
        http_len = tcp_len - tcp_buff->doff * 4;
        sb->csum = 0;
        sb->csum = csum_partial((unsigned char *)http_buff, http_len, 0);
        // fix tcp checksum
        tcp_buff->check = 0;
tcp_buff->check = csum_tcpudp_magic(sb->nh.iph->saddr,sb->nh.iph->daddr, tcp_len, IPPROTO_TCP, csum_partial((unsignedchar *)tcp_buff, tcp_buff->doff * 4, sb->csum));
        // fix ip checksum
        sb->nh.iph->check = 0;
        sb->nh.iph->check = ip_fast_csum((unsigned char *)sb->nh.iph, sb->nh.iph->ihl);
        return NF_ACCEPT;
}


int init_module()
{
        nfho_in.hook = hook_func_in;
        nfho_in.hooknum  = NF_IP_PRE_ROUTING;
        nfho_in.pf   = PF_INET;
        nfho_in.priority = NF_IP_PRI_FIRST;
       
        nfho_out.hook = hook_func_out;
        nfho_out.hooknum  = NF_IP_LOCAL_OUT;
        nfho_out.pf   = PF_INET;
        nfho_out.priority = NF_IP_PRI_FIRST;

        nf_register_hook(&nfho_in);       
        nf_register_hook(&nfho_out);

        return 0;
}

void cleanup_module()
{
        nf_unregister_hook(&nfho_in);
        nf_unregister_hook(&nfho_out);
}

[ 本帖最后由 laughmetal 于 2009-3-1 23:41 编辑 ]

论坛徽章:
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
2 [报告]
发表于 2009-03-01 23:06 |只看该作者
LZ先禁用一下Smilies。把代码排一下版,这样看着比较累。

[ 本帖最后由 Godbach 于 2009-3-1 23:09 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-03-01 23:08 |只看该作者
呵呵,小弟是个新手,谢谢大哥关心!!

论坛徽章:
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
4 [报告]
发表于 2009-03-01 23:11 |只看该作者
你在PREROUTING和LOCALOUT处分别注册了hook函数啊。

论坛徽章:
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
5 [报告]
发表于 2009-03-01 23:14 |只看该作者
// 执行到下面就死机了
        sb = skb_copy(sb, 1);
        *skb = sb;   

那你判断skb_copy是否成功了吗?

论坛徽章:
0
6 [报告]
发表于 2009-03-01 23:16 |只看该作者

回复 #4 Godbach 的帖子

在进入的时候修改目的IP指向自己,交给协议栈和用户态程序处理,再从本机发出来的时候将源IP修改成原先请求的192.168.1.1,请问这个思路是不是对的呢?

[ 本帖最后由 laughmetal 于 2009-3-1 23:28 编辑 ]

论坛徽章:
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
7 [报告]
发表于 2009-03-01 23:18 |只看该作者
那你为什么不直接修改skb,还要执行一下skb_copy干嘛呢?

论坛徽章:
0
8 [报告]
发表于 2009-03-01 23:19 |只看该作者

回复 #5 Godbach 的帖子

谢谢各位的回复!

我把return NF_ACCEPT; 放在sb = skb_copy(sb, 1);下面还是死。。。
把printk("data out\n");放在return NF_ACCEPT;前面都能死机。。。
我是在虚拟机里做的,怎么才能找出死机原因呢?

论坛徽章:
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 [报告]
发表于 2009-03-01 23:20 |只看该作者
你的死机具体的现象是什么?

论坛徽章:
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
10 [报告]
发表于 2009-03-01 23:21 |只看该作者
// 执行到下面就死机了

        sb = skb_copy(sb, 1);
        *skb = sb;      

        tcp_buff = (struct tcphdr *)(sb->data + sb->nh.iph->ihl * 4);
        http_buff = (unsigned char *)tcp_buff + tcp_buff->doff * 4;

检查一下这几个指针是否有效。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP