免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 7881 | 回复: 21

[网络子系统] 关于netfilter修改数据包的问题 [复制链接]

论坛徽章:
0
发表于 2014-03-19 16:03 |显示全部楼层
最近在做一个加密网关的项目,网关采用linux系统,要在网关上对经过网关的数据进行加密以及解密工作,下面是写的一个简单的修改数据包的代码
  1. static unsigned int send(unsigned int hooknum, struct sk_buff * skb,
  2.                                   const struct net_device * in, const struct net_device * out,
  3.                                   int (*okfn)(struct sk_buff *))
  4. {
  5.         struct iphdr* iph;
  6.         struct udphdr* udph;
  7.         struct tcphdr* tcph;
  8.         unsigned char *data = NULL;
  9.         int datalen;
  10.     int ret = 0;

  11.         __u16 dst_port,src_port;
  12.         __be32 myip;

  13.         if(skb)
  14.         {
  15.                 iph = (struct iphdr *)skb_header_pointer(skb,0,0,NULL);
  16.                 if(iph)
  17.                 {
  18.                 if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)
  19.                 {
  20.                         myip = in_aton(dstIP);
  21.                         if(iph->daddr == myip)
  22.                         {
  23.                                 if(iph->protocol == IPPROTO_UDP)
  24.                             {
  25.                                         udph = (struct udphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  26.                                     data = (char *)skb_header_pointer(nskb,TOT_HDR_LEN,0,NULL);
  27.                                     datalen = ntohs(iph->tot_len)-TOT_HDR_LEN;
  28.                                 }
  29.                                 else if(iph->protocol == IPPROTO_TCP)
  30.                                 {
  31.                                         tcph = (struct tcphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  32.                                         int offlen = IP_HDR_LEN + tcph->doff*4;
  33.                                         data = (char *)skb_header_pointer(skb,offlen,0,NULL);
  34.                                         datalen = ntohs (iph->tot_len)-offlen;
  35.                                 }

  36.                                 int j;
  37.                                 for(j=0; j<datalen; j++)
  38.                                 {
  39.                                         data[j] += 1;
  40.                                 }
  41.                                 printk("encrypted\n");
  42.                 iph->check = 0;
  43.                             ip_send_check(iph);
  44.                         }
  45.                 }
  46.                 }
  47.         }
  48.         return NF_ACCEPT;
  49. }
复制代码
hook点放在POST_ROUTING处,pri为last。同时还写了简单的udpclient与udpserver作为测试。
现在问题是,当udpclient运行在linux网关上时,udpserver可以收到加密后的报文。但是,当udpclient运行在linux网关后的内网时,udpserver收不到加密后的报文,而在udpserver运行的pc上用wireshark进行抓包却抓到了由网关发来的加密后的报文。
恳请各位大大帮小弟解答下这是什么原因,感激不尽

论坛徽章:
0
发表于 2014-03-19 16:20 |显示全部楼层
1、代码不完整吧,
if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)
dstIP在哪里?
2、用wireshark能抓到包,那看看IP、端口是不是与UDPserver一致

论坛徽章:
0
发表于 2014-03-19 16:37 |显示全部楼层
dstIP是挂载模块之后在用户态由另一个函数传递给内核,wireshark抓包看了port、ip这些都是没问题的回复 2# lonelyair


   

论坛徽章:
0
发表于 2014-03-19 16:52 |显示全部楼层
主机已经能收到包,说明你修改包没问题啊。
确认UDPserver没问题?

论坛徽章:
0
发表于 2014-03-19 16:53 |显示全部楼层
udpserver应该没问题,因为在加载模块前udpserver是可以print出client发送的信息的回复 4# lonelyair


   

论坛徽章:
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
发表于 2014-03-19 17:08 |显示全部楼层
回复 5# humengez

你的代码里面还有 TCP 的相关代码,测试中用的是只是 UDP 吗,IP 校验和计算是否正确
   

论坛徽章:
0
发表于 2014-03-19 17:13 |显示全部楼层
目前是只测了udp,ip校验和也应该没问题,一是我没有动ip报头里的东西,二是wireshark抓到的包里ipchecksum也是correct回复 6# Godbach


   

论坛徽章:
0
发表于 2014-03-19 17:21 |显示全部楼层
LZ能否多公开点的源码信息啊,靠猜可不靠谱啊

论坛徽章:
0
发表于 2014-03-19 17:24 |显示全部楼层
本帖最后由 humengez 于 2014-03-19 17:25 编辑

回复 8# lonelyair
  1. #define NIPQUAD(addr)\
  2. ((unsigned char *)&addr)[0],\
  3. ((unsigned char *)&addr)[1],\
  4. ((unsigned char *)&addr)[2],\
  5. ((unsigned char *)&addr)[3]

  6. #include <linux/module.h>
  7. #include <linux/kernel.h>
  8. #include <linux/init.h>

  9. #include <linux/netfilter.h>
  10. #include <linux/types.h>
  11. #include <linux/version.h>
  12. #include <linux/skbuff.h>
  13. #include <linux/ip.h>
  14. #include <linux/netfilter.h>
  15. #include <linux/netfilter_ipv4/ip_tables.h>
  16. #include <linux/netdevice.h>
  17. #include <linux/if_ether.h>
  18. #include <linux/if_packet.h>
  19. #include <linux/inet.h>
  20. #include <linux/string.h>
  21. #include <net/tcp.h>
  22. #include <net/udp.h>
  23. #include <net/icmp.h>
  24. #include <linux/netfilter_ipv4.h>


  25. MODULE_LICENSE("GPL");
  26. MODULE_AUTHOR("who");

  27. #define IP_HDR_LEN 20
  28. #define UDP_HDR_LEN 8
  29. #define TOT_HDR_LEN 28
  30. #define ADDRLEN 16
  31. static char dstIP[ADDRLEN] = {0};

  32. #define SOCKET_OPT_BASE 128
  33. #define SOCKET_OPT_SETTARGET (SOCKET_OPT_BASE)
  34. #define SOCKET_OPT_GETTARGET (SOCKET_OPT_BASE)
  35. #define SOCKET_OPT_MAX (SOCKET_OPT_BASE+1)

  36. static struct nf_hook_ops send_ops;
  37. static struct nf_hook_ops rcv_ops;

  38. struct rtphdr
  39. {
  40.         __u8 cc:4;
  41.         __u8 x:1;
  42.         __u8 p:1;
  43.         __u8 v:2;
  44.         __u8 pt:7;
  45.         __u8 m:1;

  46.         __u16 seq;
  47.         __u16 ts;
  48.         __u32 ssrc;
  49.         __u32 csrc[1];
  50. };

  51. static int recv_cmd(struct sock *sk,int cmd, void __user *user,unsigned int len)
  52. {
  53.         int ret = 0;
  54.         if(cmd == SOCKET_OPT_SETTARGET)
  55.         {
  56.                 memset(dstIP,0,ADDRLEN);
  57.                 ret = copy_from_user(dstIP,user,len);
  58.                 if(ret != 0)
  59.                 {
  60.                       printk("error: can not copy data from userspace\n");
  61.                       return -1;
  62.                 }
  63.                 printk("The target IP from User: %s \n",dstIP);
  64.         }
  65.         return ret;
  66. }

  67. static int send_cmd(struct sock *sk,int cmd, void __user *user,int *len)
  68. {
  69.         int ret = 0;
  70.         if(cmd == SOCKET_OPT_GETTARGET)
  71.         {
  72.                 if(0!=(ret = copy_to_user(user,dstIP,ADDRLEN)))
  73.                 {
  74.                       printk("error: can not copy data to userspace\n");
  75.                       return -1;
  76.                 }
  77.                 printk("The target IP to User: %s \n",dstIP);
  78.         }
  79.         return ret;
  80. }

  81. static struct nf_sockopt_ops my_sockops = {
  82.         .pf = PF_INET,
  83.         .set_optmin = SOCKET_OPT_SETTARGET,
  84.         .set_optmax = SOCKET_OPT_MAX,
  85.         .set = recv_cmd,
  86.         .get_optmin = SOCKET_OPT_GETTARGET,
  87.         .get_optmax = SOCKET_OPT_MAX,
  88.         .get = send_cmd
  89. };

  90. static int index = 1;

  91. static unsigned int send(unsigned int hooknum, struct sk_buff * skb,
  92.                                   const struct net_device * in, const struct net_device * out,
  93.                                   int (*okfn)(struct sk_buff *))
  94. {
  95.         struct iphdr* iph;
  96.         struct udphdr* udph;
  97.         struct tcphdr* tcph;
  98.         unsigned char *data = NULL;
  99.         int datalen;
  100.     int ret = 0;

  101.         __u16 dst_port,src_port;
  102.         __be32 myip;

  103.         if(skb)
  104.         {
  105.                 iph = (struct iphdr *)skb_header_pointer(skb,0,0,NULL);
  106.                 if(iph)
  107.                 {
  108.                 if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)
  109.                 {
  110.                         myip = in_aton(dstIP);
  111.                         if(iph->daddr == myip)
  112.                         {
  113.                                 if(iph->protocol == IPPROTO_UDP)
  114.                             {
  115.                                         udph = (struct udphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  116.                                     data = (char *)skb_header_pointer(nskb,TOT_HDR_LEN,0,NULL);
  117.                                     datalen = ntohs(iph->tot_len)-TOT_HDR_LEN;
  118.                                 }
  119.                                 else if(iph->protocol == IPPROTO_TCP)
  120.                                 {
  121.                                         tcph = (struct tcphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  122.                                         int offlen = IP_HDR_LEN + tcph->doff*4;
  123.                                         data = (char *)skb_header_pointer(skb,offlen,0,NULL);
  124.                                         datalen = ntohs (iph->tot_len)-offlen;
  125.                                 }
  126.                                         int j;
  127.                                     for(j=0; j<datalen; j++)
  128.                                     {
  129.                                             data[j] += 1;
  130.                                     }
  131.                                     printk("encrypted\n");
  132.                     iph->check = 0;
  133.                                 ip_send_check(iph);
  134.                         }
  135.                 }
  136.                 }
  137.         }
  138.         return NF_ACCEPT;
  139. }

  140. static unsigned int rcv(unsigned int hooknum, struct sk_buff * skb,
  141.                                   const struct net_device * in, const struct net_device * out,
  142.                                   int (*okfn)(struct sk_buff *))
  143. {
  144.         struct iphdr* iph;
  145.         struct udphdr* udph;
  146.         struct tcphdr* tcph;
  147.         unsigned char *data = NULL;
  148.         int datalen;
  149.         struct rtphdr * rtph;
  150.     int ret = 0;

  151.         __u16 dst_port,src_port;
  152.         __be32 myip;

  153.         if(skb)
  154.         {
  155.                 iph = (struct iphdr *)skb_header_pointer(skb,0,0,NULL);
  156.                 if(iph)
  157.                 {
  158.                 if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)
  159.                 {
  160.                         myip = in_aton(dstIP);
  161.                         if(iph->saddr == myip)
  162.                         {
  163.                                 if(iph->protocol == IPPROTO_UDP)
  164.                             {
  165.                                         udph = (struct udphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  166.                                     data = (char *)skb_header_pointer(skb,TOT_HDR_LEN,0,NULL);
  167.                                     datalen = ntohs(iph->tot_len)-TOT_HDR_LEN;
  168.                                 }
  169.                                 else if(iph->protocol == IPPROTO_TCP)
  170.                                 {
  171.                                         tcph = (struct tcphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  172.                                         int offlen = IP_HDR_LEN + tcph->doff*4;
  173.                                         data = (char *)skb_header_pointer(skb,offlen,0,NULL);
  174.                                         datalen = ntohs (iph->tot_len)-offlen;
  175.                                 }
  176.                                 int m;
  177.                                 for(m = 0; m<datalen; m++)
  178.                                 {
  179.                                         data[m] -=1;
  180.                                 }
  181.                                 printk("discpered\n");
  182.                                 iph->check = 0;
  183.                                 ip_send_check(iph);
  184.                         }
  185.                 }
  186.                 }
  187.         }
  188.         return NF_ACCEPT;
  189. }

  190. static int __init init(void)
  191. {

  192.   send_ops.hook = send;
  193.   send_ops.hooknum = NF_INET_POST_ROUTING;
  194.   send_ops.pf = PF_INET;
  195.   send_ops.priority = NF_IP_PRI_LAST;

  196.   rcv_ops.hook = rcv;
  197.   rcv_ops.hooknum = NF_INET_POST_ROUTING;
  198.   rcv_ops.pf = PF_INET;
  199.   rcv_ops.priority = NF_IP_PRI_FIRST;

  200.   nf_register_sockopt(&my_sockops);
  201.   nf_register_hook(&send_ops);
  202.   nf_register_hook(&rcv_ops);
  203. }

  204. static void __exit fini(void)
  205. {
  206.     nf_unregister_hook(&send_ops);
  207.         nf_unregister_hook(&rcv_ops);
  208.         nf_unregister_hook(&my_sockops);
  209.     printk("%s\n", "remove modify skb module.");
  210. }

  211. module_init(init);
  212. module_exit(fini);
复制代码
这是全部代码,rtphdr目前用不到,是准备以后进一步开发用的
   

论坛徽章:
0
发表于 2014-03-19 17:45 |显示全部楼层
我现在在udpserver上的LOCAL_IN点放了一个监听模块,确定包的发送和接受是都没问题的,修改过的数据包已经到了LOCAL_IN点,问题是他为什么没传给上层的应用。。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP