免费注册 查看新帖 |

Chinaunix

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

[网络子系统] 利用netfilter在内核修改IP地址并转发---求教!!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-03-31 09:55 |只看该作者 |倒序浏览
首先说明问题:
三台机器相连A--B---C,中间一台B作为A,C的默认网关。IP地址分别为:10.1.1.3----10.1.1.1 / 169.1.1.3---169.1.1.1。
利用下面的程序在B截获从A-->C的包,并对截获的包进行目的ip地址和源ip地址修改,校验和后发出。
现象:利用wireshark观察,B主机的wireshark可以截获到2个包,一个输入的一个地址转化后的,都没有错误提示。但是在C却收到的是以下信息的包:
对比B和C的wireshark发现,只有一个地方不一直:在B中是0800 但传到C就成了0004了。。。。。。。求指导!!!谢谢谢谢!!!
  1. #include<linux/init.h>
  2. #include<linux/module.h>
  3. #include<linux/netfilter.h>
  4. #include<linux/netfilter_ipv4.h>
  5. #include<linux/socket.h>
  6. #include<linux/skbuff.h>
  7. #include<linux/netdevice.h>
  8. #include<linux/inet.h>
  9. #include<net/ip.h>
  10. #include<net/tcp.h>

  11. #define ETHALEN 14
  12. #define ETH_ALEN 6
  13. MODULE_LICENSE("GPL");
  14. MODULE_AUTHOR("123");

  15. //#define ETH_P_803 0x0001
  16. #define ETH_P_IP 0x0800
  17. unsigned char src_mac1[6] = {0x00,0x24,0x7E,0x0E,0x0A,0x8A}; //169.1.1.3
  18. unsigned char dst_mac1[6] = {0xEC,0x88,0x8F,0xEA,0x4D,0xAC}; //169.1.1.1
  19. //unsigned char src_mac2[6] = {};
  20. //unsigned char dst_mac2[6] = {};

  21. struct nf_hook_ops nfho;

  22. static unsigned int checksum(
  23.         unsigned int hooknum,
  24.         struct sk_buff *__skb,
  25.         const struct net_device *in,
  26.         const struct net_device *out,
  27.         int (*okfn)(struct sk_buff *)
  28. )
  29. {
  30.         struct sk_buff *skb;
  31.         struct net_device *dev;
  32.         struct ethhdr *eth_out;
  33.         //struct ethhdr *eth_in;

  34.         struct iphdr *iph;
  35.         struct tcphdr *tcph;
  36.         int tot_len;
  37.         int iph_len;
  38.         int tcph_len;
  39.         int ret;

  40.         skb = __skb;
  41.         if(skb == NULL)
  42.                 return NF_ACCEPT;
  43.         iph = ip_hdr(skb);
  44.         if(iph == NULL)
  45.                 return NF_ACCEPT;
  46.         tot_len = ntohs(iph->tot_len);
  47.         if(iph->daddr == in_aton("192.168.137.1")) //查看目的IP地址!对是本IP地址的包进行以下操作
  48.         {
  49.                 iph_len = ip_hdrlen(skb); //获取ip首部长度
  50.                 skb_pull(skb,iph_len); //skb->data指针定位到传输层
  51.                 skb_reset_transport_header(skb);//重置首部长度,现在的首部长度包括了的ip首部长度??
  52.                 if(iph->protocol == IPPROTO_TCP) //TCP协议
  53.                 {
  54.                         tcph = tcp_hdr(skb);
  55.                         tcph_len = tcp_hdrlen(skb);
  56.                         if(tcph->dest==htons(8888)) //根据自己的需求来进行过滤数据包
  57.                         {
  58.                                 iph->saddr = in_aton("169.1.1.3"); //修改源IP地址(本地的一个IP地址)
  59.                                 iph->daddr = in_aton("169.1.1.1"); //修改目的IP地址(与本机相连的一个主机的IP地址)
  60.                                 dev = dev_get_by_name(&init_net,"eth1"); //获取输出dev信息,这里eth1 对应的是169.1.1.3的..
  61.                                 tcph->check = 0;
  62.                                 skb->csum = csum_partial((unsigned char *)tcph,tot_len-iph_len,0);       
  63.                                 tcph->check = csum_tcpudp_magic(iph->saddr,iph->daddr,ntohs(iph->tot_len)-iph_len,iph->protocol,skb->csum);
  64.                                 iph->check = 0;
  65.                                 ip_send_check(iph);
  66.                                 skb->ip_summed = CHECKSUM_NONE;
  67.                                 skb->pkt_type = PACKET_OTHERHOST;
  68.                                 skb->dev = dev;
  69.                                 //skb->protocol = ETH_P_803;
  70.                                 skb_push(skb,iph_len);        //在返回之前,先将skb中的信息恢复至原始L3层状态
  71.                                 //skb_reset_transport_header(skb);
  72.                                 eth_out = (struct ethhdr *)skb_push(skb,ETHALEN);//将skb->data指向l2层
  73.                                 eth_out->h_proto= ETH_P_IP;                        //设置MAC中的 类型
  74.                                 memcpy(eth_out->h_dest,src_mac1,ETH_ALEN);        //设置MAC中的 目的IP地址
  75.                                 memcpy(eth_out->h_source,dst_mac1,ETH_ALEN);        //设置MAC中的 源IP地址

  76.                                 ret = dev_queue_xmit(skb); //调用...发出
  77.                                 if(ret < 0 )
  78.                                 {
  79.                                         printk("dev_queue_xmit()error\n");
  80.                                         goto out;
  81.                                 }
  82.                                 return NF_STOLEN;
  83.                         }
  84.                 }
  85.                 skb_push(skb,iph_len);        //在返回之前,先将skb中的信息恢复至原始L3层状态
  86.                 skb_reset_transport_header(skb);
  87.         }

  88.         return NF_ACCEPT;
  89. out:
  90.         //dev_put(dev);
  91.         //free(skb);
  92.         return NF_DROP;
  93. }

  94. static int __init filter_init(void)
  95. {
  96.         int ret;

  97.         nfho.hook = (nf_hookfn*)checksum;
  98.         nfho.pf = AF_INET;
  99.         nfho.hooknum = NF_INET_PRE_ROUTING;
  100.         nfho.priority = NF_IP_PRI_FIRST;

  101.         ret = nf_register_hook(&nfho);
  102.         if(ret<0)
  103.         {
  104.                 printk("%s\n","can't modify skb hook!");
  105.                 return ret;
  106.         }
  107.         return 0;
  108. }

  109. static void filter_fini(void)
  110. {
  111.         nf_unregister_hook(&nfho);
  112. }

  113. module_init(filter_init);
  114. module_exit(filter_fini);
复制代码

论坛徽章:
0
2 [报告]
发表于 2016-03-31 11:14 |只看该作者
真心求教啊,有点着急~~~~~~~~大神救救我吧

论坛徽章:
0
3 [报告]
发表于 2016-03-31 19:03 |只看该作者
自己再顶一下~~  

论坛徽章:
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 [报告]
发表于 2016-03-31 19:14 |只看该作者
回复 1# hl626818

tcph = tcp_hdr(skb);


数据包在 IP 层的时候,调用这个接口,你要确认一下是否真的是 tcp 的 header。看一下 tcp_hdr 的代码吧。

根据很早的老经验,这个接口在 IP 层调用的话,返回的 ip hdr。


   

论坛徽章:
0
5 [报告]
发表于 2016-03-31 20:48 |只看该作者
首先谢谢您的回复。
虽然还没测试,但应该不会由问题,因为在tcph = tcp_hdr(skb)后面对端口号的判断可以正确实现:对地址的转换都能完成,本机能转发数据,另一台机器能收到....只是收到的有问题。
不知道为啥子另一台机器的protocol变成了0x0004??  额 好像发现了什么...我去查查资料
回复 4# Godbach


   

论坛徽章:
0
6 [报告]
发表于 2016-04-05 15:40 |只看该作者
好吧,自己来回答: 虽然没有验证,但应该是79行的字节序出错了。 由于是截获包转发包,所以向以太网首部中填充类型字段完全没有必要(截获的包自己就有),所以我就将79屏蔽掉。
然后就正常了......再次感慨一下:自己一个人调程序真TM痛苦
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP