免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: meijusan123
打印 上一主题 下一主题

[网络子系统] linux 协议栈 IP头 手动封装 [复制链接]

论坛徽章:
0
51 [报告]
发表于 2009-08-21 11:51 |只看该作者
原帖由 meijusan123 于 2009-8-21 11:24 发表


尝试了“Godbach”兄弟所说的方法,ipip包是封装发出可以啦。但,也出现了新问题,之前的skb释放问题没解决,所以发出数据包时,出现了两个包,一个是skb所指的,一个是nskb所指的。
现在,我想尝试 ...


你这样当然能发出去了,但是我觉得有两个问题:
1、你新的IP首部装上去了,怎么没有看到你重新查询路由方面的代码?
2、应该NF_DROP吧,如果你ACCEPT,不是有两个包了么?那不混乱了?
3、直接NF_DROP干脆些,把包释放工作交给netfilter,我起先说的STONE,是把释放工作交给自己。(不过你说要oops,这个需要找原因了,没有完整代码,没有发言权)

这种方式,是一种粗暴的处理方式。因为完全打扰了正常的包处理流程。比如,如果还要做NAT那些就没法了。
我觉得还是应该想法子“偷天换日”,直接释放包,然后用新的包代替之。你说这种也要OOPS,你再贴贴你这种方式的完整代码呢??我觉得理论上是完全可行的。

论坛徽章:
0
52 [报告]
发表于 2009-08-21 12:32 |只看该作者
原帖由 独孤九贱 于 2009-8-21 11:51 发表


你这样当然能发出去了,但是我觉得有两个问题:
1、你新的IP首部装上去了,怎么没有看到你重新查询路由方面的代码?
2、应该NF_DROP吧,如果你ACCEPT,不是有两个包了么?那不混乱了?
3、直接NF_DROP干 ...





回答:
1.我是还没写路由代码,因为我先本机tcpdump出发送的包的结构进行验证封装的过程,如果需要发出去,就如“九贱”兄所说,是需要重新路由的,谢谢提醒;
2.现在是有两个包发出啦,是比较乱,如果NF_DROP下去,netfilter框架流程会被打乱,下面的netfilter就没包流过;
3.还是需要偷天换日,释放原来skb,保留nskb信息,但free是有问题哦。
........

                int addiphlen =0;
                int max_headroom=0;
                       unsigned int    dst =0x80afa8c0;        
                       unsigned int    src =0x82afa8c0;      
                struct sk_buff *nskb=NULL;
                struct net_device *dev = skb->dst->dev;
                       addiphlen = skb->nh.iph->ihl *4;
        
                max_headroom = (LL_RESERVED_SPACE(dev)+sizeof(struct iphdr));
                if (skb_headroom(skb) < max_headroom) {               
                nskb = skb_realloc_headroom(skb, max_headroom);
                if (nskb == NULL){
                        kfree_skb(skb);
                        return -ENOMEM;
                }
                if (skb->sk)
                        skb_set_owner_w(nskb,skb->sk);
                        kfree(skb);//<---释放问题,
                 *pskb=nskb;//<----添加,有问题哦。
                }
               
                nskb->h.raw = nskb->nh.raw;
                nskb->nh.raw = skb_push(nskb, sizeof(struct iphdr));
                iph                 =        nskb->nh.iph;
                iph->version        =        hdr->version;
                iph->ihl        =        hdr->ihl;
                iph->tos        =        hdr->tos;
                iph->tot_len        =        htons(ntohs(hdr->tot_len) + addiphlen);
                iph->id                =        hdr->id;
                iph->frag_off        =        hdr->frag_off;
                iph->ttl        =        hdr->ttl;
                iph->protocol        =        IPPROTO_IPIP;
                iph->daddr        =        dst;
                iph->saddr        =        src;
               
                iph->check = 0;               
                iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
               
                dev_queue_xmit(nskb);
                printk("accept the out packet!number:[%d]\n",out_accept_cnt);
        }
return NF_ACCEPT;

........

论坛徽章:
0
53 [报告]
发表于 2009-08-21 13:10 |只看该作者

回复 #52 meijusan123 的帖子

kfree(skb);//<---释放问题
是你笔误还是怎么地?
应是kfree_skb(skb);

*pskb=nskb;//<----添加,有问题哦
这样替换是有问题,太粗暴了。至少原来的skb是经过netfilter处理过的。例如状态检测,例如PRE_ROUTING等等。要的是这个效果,而不是如此简单的一句代码。我再想一想要处理哪些细节吧。

算了,想起来脑壳痛,还是在连接跟踪结束后加IP hdr,直接递交协议栈发送。然后在连接跟踪未开始时拆包。这样就可以绕过Netfilter了。完全透明。

[ 本帖最后由 独孤九贱 于 2009-8-21 13:20 编辑 ]

论坛徽章:
0
54 [报告]
发表于 2009-08-21 14:07 |只看该作者
这个我自己也写过,开始也一直出现incorrect chechsum,应该是校验的范围出现了问题,因为IP包的负载部分要考虑一下!

论坛徽章:
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
55 [报告]
发表于 2009-08-21 14:20 |只看该作者
IP部分只需要计算IP头的校验和。不用考虑内容的。

论坛徽章:
0
56 [报告]
发表于 2009-08-22 20:13 |只看该作者

回复 #54 iorifreedom 的帖子

checksum,之前我考虑到了,应该不是这的问题。还是之前“九贱”兄说的对,释放有问题。还在考虑

论坛徽章:
0
57 [报告]
发表于 2009-08-22 20:20 |只看该作者

回复 #55 Godbach 的帖子

是呀,如“Godbach ”所说,如果修改了ip头只要修改ip头部分的checksum。
随便问下:skb->csum没改,程序可以照样可以通过,还不太清楚skb->csum到底要在什么情况下修改。

论坛徽章:
0
58 [报告]
发表于 2009-08-22 20:39 |只看该作者
原帖由 独孤九贱 于 2009-8-21 13:10 发表
kfree(skb);//



不好意思“九贱”兄弟,是笔误刚才:)。该是kfree_skb()这个。
还是你说的那样,可能这样释放是比较粗暴,好像有别的什么都没考虑到,是不是还要检测skb->cloned的值或是赋为0,还有引用计数清理等一些动作,不知道还有什么,可以帮我想想。

现在这个模块是挂在netfiter的hook上的,没办法,只能这这样的流程上走过,大概不能让他直接发送使之透明。

现在,我有两套方案,我想说了让你看看,我的看法是对还是错:
第一套方案:.就是沿着现在的思路,使用nskb新申请的内存空间来封装ip头,但,问题是之前的skb的旧空间咋能有效的释放掉,是个大问题,让数据包继续在netfiter的框架上继续走下去;

第二套方案:不再是之前那种思想,不要重新自己申请一个nskb内存,直接使用之前的skb空间,只要把现有的skb->data到skb->tail之间的内容拷贝出来放在一个临时空间里,继续使用skb_reserve()把data和tail同时往后移动iphdr的空间,接着再把临时空间里的内容拷贝进data之后的内存位置,接着,就可以使用skb_push()再添加一个自己的ip头了。(这个方案,肯能是可以使用的,但,缺点是,如果我要添加一个很大头部,比如需要200字节,难道,一开始的skb就可以足够使用嘛???)

随便问下,当我们socket发送数据包时,在协议栈中缓冲区的申请skb是不是固定大小的,如果是固定有个1500字节那就肯定够以后使用,如果只是按现有发送数据+几个要封装头的大小,那,方案二可能就不行啦。肯定不够用呀???


九贱兄,我很想看看你的说法。很有建设性!!

论坛徽章:
0
59 [报告]
发表于 2009-08-24 15:04 |只看该作者
我觉得:
-1. skb_reverse还是不要在旧的skb使用(规矩点嘛)

0 . 没看懂1, 2方案啥意思

1. 继续沿着nf走不太好哈, 不如加好SG头(local/peer)后 释放dst, 释放nf_reset, 然后重新查路由并设置sk(如果有的话), 然后重新执行nf:       
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
                       dst_output);
最后当前hook里面返回STOLE



另外linux不是有XFRM和KLIPS这样优秀的代码为啥不用泥?

论坛徽章:
0
60 [报告]
发表于 2009-08-24 15:12 |只看该作者
>是不是还要检测skb->cloned的值或是赋为0,还有引用计数清理等一些动作,不知道还有什么,可以帮我想想。


你说这几个不用考虑, 发IP玩完报文释放时候会考虑的。

我个人觉得只要把nh h指对位置, nf, dst释放了, 就好了没啥要考虑的。 但这点还需要高人来确认, 俺也是来学习的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP