Chinaunix首页 | 论坛 | 博客
  • 博客访问: 77639
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 225
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-06 15:31
文章分类

全部博文(29)

文章存档

2015年(18)

2014年(11)

我的朋友

分类: LINUX

2014-03-24 16:25:23

1、NETFILTER
        数据包进入linux内核的网络层时,其总入口为kernel/linux/net/ipv4/ip_input.c的函数ip_rcv(),在对数据包进行正确性检查和校验之后,路由判断之前,会进入到一个netfilter的钩子NF_INET_PRE_ROUTING,数据包在这个钩子里进行一些处理,处理完之后,如果是接收包,则调用该钩子的ok函数,即下一步的处理函数。对于iptables来说,这里是PREROUTING规则链,能在这里设置iptables规则的只有mangle表和nat表,mangle表主要是对数据包打标记等操作。而nat表主要对数据包进行重定向,丢弃或接收数据包。

注意mangle表比nat表优先级高,所以在内核中会先处理mangle表的规则,然后再处理nat表的规则。

当路由判定后决定数据包是发往本地即Linux系统本身的,则其入口为kernel/linux/net/ipv4/ip_input.c的函数ip_local_deliver(),在这个函数最后会调用INPUT链的钩子函数NF_INET_LOCAL_IN,在这个钩子中可以设置mangle表和filter表的规则,mangle表比filter表优先级要高,filter表的主要作用是过滤数据包。

而当路由判定后数据包是发往其他主机的,则进入到kernel/linux/net/ipv4/ip_forward.c的函数ip_forward(),在函数最后同样要执行NF_INET_FORWARD这个钩子函数,在FORWARD链里,同样只能设置mangle表和filter表的规则,mangle表的优先级比filter表高。

数据包由本地发出的时候,执行到kernel/linux/net/ipv4/ip_output.c的函数__ip_local_out(),在这里会执行钩子函数NF_INET_LOCAL_OUT,在OUTPUT链里可以有mangle表、nat表、filter表的规则,优先级分别为mangle表到nat表再到filter表。

数据包在离开本机之前会调用到kernel/linux/net/ipv4/ip_output.c的函数ip_output(),这里执行的是NF_INET_POST_ROUTING钩子函数,在这个钩子里只能有manglenat表,而mangle表比nat表优先级高。
      其中,在NF_INET_PRE_ROUTING处进行DNAT,在NF_INET_POST_ROUTING处进行SNAT。
2、CODE

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>

  4. #include <linux/netfilter.h>
  5. #include <linux/types.h>
  6. #include <linux/version.h>
  7. #include <linux/skbuff.h>
  8. #include <linux/ip.h>
  9. #include <linux/netfilter.h>
  10. #include <linux/netfilter_ipv4/ip_tables.h>
  11. #include <linux/netdevice.h>
  12. #include <linux/if_ether.h>
  13. #include <linux/if_packet.h>
  14. #include <linux/inet.h>
  15. #include <linux/string.h>
  16. #include <net/tcp.h>
  17. #include <net/udp.h>
  18. #include <net/icmp.h>
  19. #include <linux/netfilter_ipv4.h>


  20. MODULE_LICENSE("GPL");
  21. MODULE_AUTHOR("who");

  22. #define IP_HDR_LEN 20
  23. #define UDP_HDR_LEN 8
  24. #define TOT_HDR_LEN 28
  25. #define ADDRLEN 16
  26. #define CHECKSUM_NONE 0
  27. static char dstIP[ADDRLEN] = {0};//接受由用户态传递过来的目标IP地址

  28. static struct nf_hook_ops send_ops;
  29. static struct nf_hook_ops rcv_ops;

  30. struct rtphdr
  31. {
  32.     __u8 cc:4;
  33.     __u8 x:1;
  34.     __u8 p:1;
  35.     __u8 v:2;
  36.     __u8 pt:7;
  37.     __u8 m:1;

  38.     __u16 seq;
  39.     __u16 ts;
  40.     __u32 ssrc;
  41.     __u32 csrc[1];
  42. };

  43. //tcp checksum计算
  44. void tcp_checksum(struct iphdr *pIph, unsigned short *ipPayload) {
  45.     unsigned long sum = 0;
  46.     unsigned short tcpLen = ntohs(pIph->tot_len) - IP_HDR_LEN;
  47.     struct tcphdr *tcphdrp = (struct tcphdr*)(ipPayload);

  48.     sum += (pIph->saddr>>16)&0xFFFF;
  49.     sum += (pIph->saddr)&0xFFFF;
  50.     
  51.     sum += (pIph->daddr>>16)&0xFFFF;
  52.     sum += (pIph->daddr)&0xFFFF;
  53.     
  54.     sum += htons(IPPROTO_TCP);
  55.     
  56.     sum += htons(tcpLen);
  57.  
  58.     tcphdrp->check = 0;
  59.     while (tcpLen > 1) {
  60.         sum += * ipPayload++;
  61.         tcpLen -= 2;
  62.     }
  63.     
  64.     if(tcpLen > 0) {
  65.         sum += ((*ipPayload)&htons(0xFF00));
  66.     }
  67.      
  68.     while (sum>>16) {
  69.           sum = (sum & 0xffff) + (sum >> 16);
  70.     }
  71.     sum = ~sum;
  72.     tcphdrp->check = (unsigned short)sum;
  73. }

  74. //udp checksum计算
  75. void udp_checksum(struct iphdr *pIph, unsigned short *ipPayload) {
  76.     register unsigned long sum = 0;
  77.     struct udphdr *udphdrp = (struct udphdr*)(ipPayload);
  78.     unsigned short udpLen = htons(udphdrp->len);
  79.     
  80.     sum += (pIph->saddr>>16)&0xFFFF;
  81.     sum += (pIph->saddr)&0xFFFF;
  82.     
  83.     sum += (pIph->daddr>>16)&0xFFFF;
  84.     sum += (pIph->daddr)&0xFFFF;
  85.     
  86.     sum += htons(IPPROTO_UDP);
  87.     
  88.     sum += udphdrp->len;
  89.  
  90.     udphdrp->check = 0;
  91.     while (udpLen > 1) {
  92.         sum += * ipPayload++;
  93.         udpLen -= 2;
  94.     }
  95.     
  96.     if(udpLen > 0) {
  97.         sum += ((*ipPayload)&htons(0xFF00));
  98.     }
  99.      
  100.     while (sum>>16) {
  101.           sum = (sum & 0xffff) + (sum >> 16);
  102.     }
  103.     
  104.     sum = ~sum;
  105.     udphdrp->check = ((unsigned short)sum == 0x0000)?0xFFFF:(unsigned short)sum;
  106. }

  107. //发送加密函数
  108. static unsigned int send(unsigned int hooknum, struct sk_buff * skb,
  109.                                   const struct net_device * in, const struct net_device * out,
  110.                                   int (*okfn)(struct sk_buff *))
  111. {
  112.     struct iphdr* iph;
  113.     struct udphdr* udph;
  114.     struct tcphdr* tcph;
  115.     unsigned char *data = NULL;
  116.     unsigned short *ippay = NULL;
  117.     int datalen;
  118.     int mylen;
  119.     int ret = 0;

  120.     __u16 dst_port,src_port;
  121.     __be32 myip;

  122.     if(skb)
  123.     {
  124.         iph = (struct iphdr *)skb_header_pointer(skb,0,0,NULL);
  125.         if(iph)
  126.         {
  127.         if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)
  128.         {
  129.             myip = in_aton(dstIP);
  130.             if(iph->daddr == myip)//判断截取到的报文的目的IP地址是否为需要进行加密的IP地址
  131.             {
  132.                 ippay = (unsigned short *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  133.                 if(iph->protocol == IPPROTO_UDP)//判断报文类型
  134.              {
  135.                     udph = (struct udphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  136.                     data = (unsigned char *)skb_header_pointer(skb,TOT_HDR_LEN,0,NULL);//提取UDP报文中的载荷部分
  137.                     datalen = ntohs(iph->tot_len)-TOT_HDR_LEN;//data部分的长度

  138.                     //以下为对UDP报文中data进行加密
  139.                     int a;
  140.                     for(a=0; a<datalen; a++)
  141.                     {
  142.                         data[a] += 1;
  143.                     }
  144.                 
  145.                     //以下重新计算报文的checksum
  146.                     iph->check = 0;
  147.                     ip_send_check(iph);
  148.                     
  149.                     udp_checksum(iph,ippay);
  150.                     }
  151.                 }
  152.                 else if(iph->protocol == IPPROTO_TCP)
  153.                 {
  154.                     tcph = (struct tcphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  155.                     int offlen = IP_HDR_LEN + tcph->doff*4;
  156.                     data = (char *)skb_header_pointer(skb,offlen,0,NULL);//提取TCP报文中的载荷
  157.                     datalen = ntohs (iph->tot_len)-offlen;//data部分的长度

  158.                     //以下为对TCP报文中data进行加密
  159.                     int j;
  160.                  for(j=0; j<datalen; j++)
  161.                  {
  162.                      data[j] += 1;
  163.                  }
  164.                 
  165.                     //以下重新计算报文的checksum
  166.                     iph->check = 0;
  167.              ip_send_check(iph);
  168.                 
  169.                     tcp_checksum(iph,ippay);
  170.                 }
  171.             }
  172.         }
  173.         }
  174.     }
  175.     return NF_ACCEPT;
  176. }

  177. //接收解密函数
  178. static unsigned int rcv(unsigned int hooknum, struct sk_buff * skb,
  179.                                   const struct net_device * in, const struct net_device * out,
  180.                                   int (*okfn)(struct sk_buff *))
  181. {
  182.     struct iphdr* iph;
  183.     struct udphdr* udph;
  184.     struct tcphdr* tcph;
  185.     unsigned char *data = NULL;
  186.     unsigned short *ippay = NULL;
  187.     int datalen;
  188.     struct rtphdr * rtph;
  189.     int ret = 0;

  190.     __u16 dst_port,src_port;
  191.     __be32 myip;

  192.     if(skb)
  193.     {
  194.         iph = (struct iphdr *)skb_header_pointer(skb,0,0,NULL);
  195.         if(iph)
  196.         {
  197.         if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)
  198.         {
  199.             myip = in_aton(dstIP);
  200.             if(iph->saddr == myip)//判断截取到的报文的源IP地址是否为需要进行解密的IP地址(即从用户态传入的其他安全网关的IP地址)
  201.             {
  202.                 ippay = (unsigned short *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  203.                 if(iph->protocol == IPPROTO_UDP)//判断报文类型
  204.              {
  205.                     udph = (struct udphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  206.                  data = (char *)skb_header_pointer(skb,TOT_HDR_LEN,0,NULL);//提取UDP报文中的载荷部分
  207.                  datalen = ntohs(iph->tot_len)-TOT_HDR_LEN;//data部分的长度

  208.                             //以下为对UDP报文中data进行解密
  209.                      int a;
  210.                  for(a=0; a<datalen; a++)
  211.                  {
  212.                      data[a] -= 1;
  213.                  }

  214.                     //以下重新计算报文的checksum
  215.                     iph->check = 0;
  216.              ip_send_check(iph);
  217.                     
  218.                     udp_checksum(iph,ippay);
  219.                     }
  220.                 }
  221.                 else if(iph->protocol == IPPROTO_TCP)//判断报文类型
  222.                 {
  223.                     tcph = (struct tcphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);
  224.                     int offlen = IP_HDR_LEN + tcph->doff*4;
  225.                     data = (char *)skb_header_pointer(skb,offlen,0,NULL);//提取tcp报文中的载荷
  226.                     datalen = ntohs (iph->tot_len)-offlen;//tcp报文中的载荷长度
  227.                 
  228.                     //以下为对TCP有效载荷进行解密
  229.                 int j;
  230.                  for(j=0; j<datalen; j++)
  231.                  {
  232.                      data[j] -= 1;
  233.                  }
  234.                 
  235.                     //以下重新计算报文的checksum
  236.                     iph->check = 0;
  237.              ip_send_check(iph);
  238.                     
  239.                     tcp_checksum(iph,ippay);
  240. }
  241.             }
  242.         }
  243.         }
  244.     }
  245.     return NF_ACCEPT;
  246. }

  247. static int __init init(void)
  248. {

  249.   send_ops.hook = send;
  250.   send_ops.hooknum = NF_INET_POST_ROUTING;
  251.   send_ops.pf = PF_INET;
  252.   send_ops.priority = NF_IP_PRI_LAST;

  253.   rcv_ops.hook = rcv;
  254.   rcv_ops.hooknum = NF_INET_PRE_ROUTING;
  255.   rcv_ops.pf = PF_INET;
  256.   rcv_ops.priority = NF_IP_PRI_LAST;

  257.   nf_register_hook(&send_ops);
  258.   nf_register_hook(&rcv_ops);
  259. }

  260. static void __exit fini(void)
  261. {
  262.     nf_unregister_hook(&send_ops);
  263.     nf_unregister_hook(&rcv_ops);
  264.     printk("%s\n", "remove modify skb module.");
  265. }

  266. module_init(init);
  267. module_exit(fini);


阅读(1431) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~