Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3795902
  • 博文数量: 93
  • 博客积分: 3189
  • 博客等级: 中校
  • 技术积分: 4231
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-02 13:29
个人简介

出没于杭州和青岛的程序猿一枚,对内核略懂一二

文章分类

全部博文(93)

文章存档

2016年(2)

2015年(3)

2014年(11)

2013年(29)

2012年(16)

2011年(5)

2010年(5)

2009年(22)

分类: LINUX

2011-02-27 08:06:15

netfilter的target有一个SNAT实现源地址转换,但是无法实现网段的地址转换,于是就写了一个NETSNAT实现网段的地址转换。
比如:192.168.3.0/24-->192.168.2.0/24  ,当然了,有些时候也是需要进来的时候做转换的,所以就又写了一些NETDNAT的target。
 iptables的规则编写:
iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -j NETSNAT --netsnat 192.168.3.0/24-192.168.2.0/24
相反的,如果希望外网访问192.168.2.0/24的时候,转到192.168.3.0/24,则使用如下的规则:
iptables -t nat -A PREROUTING -d 192.168.2.0/24 -j NETDNAT --netdnat 192.168.2.0/24-192.168.3.0/24
欢迎大家测试提出宝贵意见。
下面是代码:
ipt_NETSNAT.h
  1. #ifndef _IPT_NETSNAT_H_target
  2. #define _IPT_NETSNAT_H_target
  3. struct ipt_NETSNAT_info{
  4.  char netsnat[41];
  5.  unsigned int excursion;
  6.  int flag;//flag=1 means destnet is big than sourcenet;

  7.     //flag=0 means destnet is small than sourcenet.

  8. };
  9. #endif
ipt_NETSNAT.c
  1. /* Netfilter Target NETSNAT
  2.  *
  3.  * (C) 2011 by liutingwei
  4.  * 2011-02-24 09:34:25
  5.  *
  6.  * This software is released under the terms of GNU GPL
  7.  *
  8.  */
  9. #include <linux/module.h>
  10. #include <linux/skbuff.h>
  11. #include <linux/ip.h>
  12. #include <linux/inet.h>
  13. #include <linux/netfilter_ipv4/ip_tables.h>
  14. #include <linux/types.h>
  15. #include <linux/if.h>
  16. #include <linux/inetdevice.h>
  17. #include <net/protocol.h>
  18. #include <net/checksum.h>
  19. #include <linux/netfilter_ipv4.h>
  20. #include <net/netfilter/nf_nat_rule.h>
  21. #include <net/netfilter/nf_nat_core.h>
  22. #include "ipt_NETSNAT.h"
  23. MODULE_LICENSE("GPL");
  24. MODULE_AUTHOR("LTW ");
  25. MODULE_DESCRIPTION("iptables net snat");
  26. static bool
  27. redirect_check(const char *tablename,
  28.         const void *e,
  29.         const struct xt_target *target,
  30.         void *targinfo,
  31.         unsigned int hook_mask)
  32. {
  33.  return true;
  34. }
  35. static unsigned int
  36. netsnat_target(struct sk_buff *skb,
  37.   const struct net_device *in,
  38.   const struct net_device *out,
  39.   unsigned int hooknum,
  40.   const struct xt_target *target,
  41.   const void *targinfo)
  42. {
  43.  struct nf_conn *ct;
  44.  struct nf_conn_nat *nat;
  45.  enum ip_conntrack_info ctinfo;
  46.  struct nf_nat_range newrange;
  47.  const struct ipt_NETSNAT_info *info=targinfo;
  48.  struct iphdr *iph;
  49.  __be32 sourceip;
  50.  __be32 newsrc;
  51.  iph=ip_hdr(skb);
  52.  sourceip=ntohl(iph->saddr);
  53.  NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
  54.  ct = nf_ct_get(skb, &ctinfo);
  55.  nat = nfct_nat(ct);
  56.  NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
  57.        || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
  58.  /* Source address is 0.0.0.0 - locally generated packet that is
  59.   * probably not supposed to be masqueraded.
  60.   */
  61.  if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
  62.   return NF_ACCEPT;
  63.  if(info->flag==1)
  64.   newsrc=htonl(sourceip+info->excursion);
  65.  else if(info->flag==0)
  66.   newsrc=htonl(sourceip-info->excursion);
  67.  else
  68.   return NF_ACCEPT;
  69.  /* Transfer from original range. */
  70.  memset(&newrange,0,sizeof(newrange));
  71.  newrange.flags|=IP_NAT_RANGE_MAP_IPS;
  72.  newrange.min_ip=newrange.max_ip=newsrc;
  73.  /* Hand modified range to generic setup. */
  74.  return nf_nat_setup_info(ct, &newrange, hooknum);
  75. }
  76. static struct xt_target netsnat_reg __read_mostly = {
  77.  .name = "NETSNAT",
  78.  .family = AF_INET,
  79.  .target = netsnat_target,
  80.  .targetsize = sizeof(struct ipt_NETSNAT_info),
  81.  .table = "nat",
  82.  .hooks = (1 << NF_IP_POST_ROUTING),
  83.  .checkentry = redirect_check,
  84.  .me = THIS_MODULE,
  85. };
  86. static int __init ipt_multisnat_init(void)
  87. {
  88.  return xt_register_target(&netsnat_reg);
  89. }
  90. static void __exit ipt_multisnat_fini(void)
  91. {
  92.  xt_unregister_target(&netsnat_reg);
  93. }
  94. module_init(ipt_multisnat_init);
  95. module_exit(ipt_multisnat_fini);
libipt_netsnat.c
  1. /* Shared library add-on to iptables to add NETSNAT support.
  2.  *
  3.  * (C) 2011 by liutingwei
  4.  * 2011-02-24 10:20:25
  5.  *
  6.  * This software is released under the terms of GNU GPL
  7.  *
  8.  */
  9. #include <stdio.h>
  10. #include <netdb.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <syslog.h>
  14. #include <getopt.h>
  15. #include <iptables.h>
  16. #include <linux/netfilter_ipv4/ip_tables.h>
  17. #include <linux/netfilter/x_tables.h>
  18. #include "ipt_NETSNAT.h"
  19. #define IPTABLES_VERSION "1.4.0"
  20. enum{
  21.  NETSNAT =1<<0,
  22. };
  23. static void NETSNAT_check(unsigned int flags)
  24. {
  25.  if((flags&NETSNAT)==0)
  26.   //== priority is higher than &

  27.   exit_error(PARAMETER_PROBLEM,"NETSNAT target: You must specify --netsnat");
  28. }
  29. /* Function which prints out usage message. */
  30. static void NETSNAT_help(void)
  31. {
  32.  printf("NETSNAT[LTW] v%s options:\n"
  33.       "--netsnat source-dest\n"
  34.    "\n"
  35.    ,IPTABLES_VERSION);
  36. }
  37. static const struct option NETSNAT_opts[] = {
  38.  {"netsnat", 1, NULL, '1'},
  39.  {NULL,0,NULL,0}
  40. };
  41. /* Function which parses command options; returns true if it
  42.    ate an option */
  43. static int NETSNAT_parse(int c, char **argv, int invert, unsigned int *flags,
  44.                       const void *entry, struct xt_entry_target **target)
  45. {
  46.  char *temp,*tempnet,*p,*n;
  47.  unsigned int sourceip;
  48.  unsigned int destip;
  49.  int mask1,mask2;
  50.  struct ipt_NETSNAT_info *info = (struct ipt_NETSNAT_info *) (*target)->data;
  51.  switch (c) {
  52.   case '1':
  53.    if (*flags&NETSNAT)
  54.     exit_error(PARAMETER_PROBLEM,
  55.       "Can't specify --netsnat twice");
  56.    *flags|=NETSNAT;
  57.    if(strlen(optarg)>37)
  58.     exit_error(PARAMETER_PROBLEM,
  59.       "\"%s\" is not a valid netsnat");
  60.    memcpy(info->netsnat,optarg,strlen(optarg));
  61.    temp=strdup(optarg);
  62.    tempnet=temp;
  63.    n=strchr(tempnet,'-');
  64.    if(n==NULL||(n+1)==NULL)
  65.     exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netsnat");
  66.    *n++=0;
  67.    p=strchr(tempnet,'/');
  68.    if(p==NULL||(p+1)==NULL)
  69.     exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netsnat");
  70.    *p++=0;
  71.    mask1=atoi(p);
  72.    sourceip=inet_network(tempnet);
  73.    tempnet=n;
  74.    p=strchr(tempnet,'/');
  75.    if(p==NULL||(p+1)==NULL)
  76.     exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netsnat");
  77.    *p++=0;
  78.    mask2=atoi(p);
  79.    destip=inet_network(tempnet);
  80.    if(mask1!=mask2)
  81.     exit_error(PARAMETER_PROBLEM,
  82.       "Source and Dest net mask not equeal");
  83.    if(mask1<0||mask1>32)
  84.     exit_error(PARAMETER_PROBLEM,
  85.       "Source and Dest net mask not valid (0-32)");
  86.    if(sourceip==(unsigned int)(-1) || destip==(unsigned int)(-1))
  87.     exit_error(PARAMETER_PROBLEM,
  88.       "Source or Dest ip not valid");
  89.    mask2=32-mask1;
  90.    sourceip=sourceip&~((1<<mask2)-1);
  91.    destip=destip&~((1<<mask2)-1);
  92.    if(sourceip<destip){
  93.     info->flag=1;
  94.     info->excursion=destip-sourceip;
  95.    }else{
  96.     info->flag=0;
  97.     info->excursion=sourceip-destip;
  98.    }
  99.    free(temp);
  100.    break;
  101.   default:
  102.    return 0;
  103.  }
  104.  return 1;
  105. }
  106. /* Saves the union ipt_targinfo in parsable form to stdout. */
  107. static void NETSNAT_save(const void *ip, const struct xt_entry_target *target)
  108. {
  109.  return;
  110. }
  111. static void NETSNAT_init(struct xt_entry_target *t)
  112. {
  113.  struct ipt_NETSNAT_info *info = (struct ipt_NETSNAT_info *) t->data;
  114.  info->flag=-1;
  115.  memset(info->netsnat,0,41);
  116.  return;
  117. }
  118. /* Prints out the targinfo. */
  119. static void NETSNAT_print(const void *ip, const struct xt_entry_target *target,
  120.                        int numeric)
  121. {
  122.  const struct ipt_NETSNAT_info *info
  123.      = (const struct ipt_NETSNAT_info *) target->data;
  124.  printf(" NETSNAT %s ", info->netsnat);
  125. }
  126. static struct iptables_target NETSNAT_target = {
  127.  .name = "NETSNAT",
  128.  .version = IPTABLES_VERSION,
  129.  .size = IPT_ALIGN(sizeof(struct ipt_NETSNAT_info)),
  130.  .userspacesize = IPT_ALIGN(sizeof(struct ipt_NETSNAT_info)),
  131.  .help = NETSNAT_help,
  132.  .parse = NETSNAT_parse,
  133.  .init = NETSNAT_init,
  134.  .final_check= NETSNAT_check,
  135.  .print = NETSNAT_print,
  136.  .save = NETSNAT_save,
  137.  .extra_opts =NETSNAT_opts,
  138. };
  139. void _init(void)
  140. {
  141.  register_target(&NETSNAT_target);
  142. }
ipt_netdnat.h
  1. #ifndef _IPT_NETDNAT_H_target
  2. #define _IPT_NETDNAT_H_target
  3. struct ipt_NETDNAT_info{
  4.  char netdnat[41];
  5.  unsigned int excursion;
  6.  int flag;//flag=1 means destnet is big than sourcenet;

  7.     //flag=0 means destnet is small than sourcenet.

  8. };
  9. #endif
ipt_netdnat.c
  1. /* Netfilter NETDNAT Target
  2.  *
  3.  * (C) 2011 by liutingwei
  4.  * 2011-02-24 11:02:47
  5.  *
  6.  * This software is released under the terms of GNU GPL
  7.  *
  8.  */
  9. #include <linux/module.h>
  10. #include <linux/skbuff.h>
  11. #include <linux/ip.h>
  12. #include <linux/inet.h>
  13. #include <linux/netfilter_ipv4/ip_tables.h>
  14. #include <linux/types.h>
  15. #include <linux/if.h>
  16. #include <linux/inetdevice.h>
  17. #include <net/protocol.h>
  18. #include <net/checksum.h>
  19. #include <linux/netfilter_ipv4.h>
  20. #include <net/netfilter/nf_nat_rule.h>
  21. #include <net/netfilter/nf_nat_core.h>
  22. #include "ipt_NETDNAT.h"
  23. MODULE_LICENSE("GPL");
  24. MODULE_AUTHOR("LTW ");
  25. MODULE_DESCRIPTION("iptables net snat");
  26. static bool
  27. redirect_check(const char *tablename,
  28.         const void *e,
  29.         const struct xt_target *target,
  30.         void *targinfo,
  31.         unsigned int hook_mask)
  32. {
  33.  return true;
  34. }
  35. static unsigned int
  36. netdnat_target(struct sk_buff *skb,
  37.   const struct net_device *in,
  38.   const struct net_device *out,
  39.   unsigned int hooknum,
  40.   const struct xt_target *target,
  41.   const void *targinfo)
  42. {
  43.  struct nf_conn *ct;
  44.  struct nf_conn_nat *nat;
  45.  enum ip_conntrack_info ctinfo;
  46.  struct nf_nat_range newrange;
  47.  const struct ipt_NETDNAT_info *info=targinfo;
  48.  struct iphdr *iph;
  49.  __be32 destip;
  50.  __be32 newdest;
  51.  iph=ip_hdr(skb);
  52.  destip=ntohl(iph->daddr);
  53.  NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING);
  54.  ct = nf_ct_get(skb, &ctinfo);
  55.  nat = nfct_nat(ct);
  56.  NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
  57.  if(info->flag==1)
  58.   newdest=htonl(destip+info->excursion);
  59.  else if(info->flag==0)
  60.   newdest=htonl(destip-info->excursion);
  61.  else
  62.   return NF_ACCEPT;
  63.  /* Transfer from original range. */
  64.  memset(&newrange,0,sizeof(newrange));
  65.  newrange.flags|=IP_NAT_RANGE_MAP_IPS;
  66.  newrange.min_ip=newrange.max_ip=newdest;
  67.  /* Hand modified range to generic setup. */
  68.  return nf_nat_setup_info(ct, &newrange, hooknum);
  69. }
  70. static struct xt_target netdnat_reg __read_mostly = {
  71.  .name = "NETDNAT",
  72.  .family = AF_INET,
  73.  .target = netdnat_target,
  74.  .targetsize = sizeof(struct ipt_NETDNAT_info),
  75.  .table = "nat",
  76.  .hooks = (1 << NF_IP_PRE_ROUTING),
  77.  .checkentry = redirect_check,
  78.  .me = THIS_MODULE,
  79. };
  80. static int __init ipt_multisnat_init(void)
  81. {
  82.  return xt_register_target(&netdnat_reg);
  83. }
  84. static void __exit ipt_multisnat_fini(void)
  85. {
  86.  xt_unregister_target(&netdnat_reg);
  87. }
  88. module_init(ipt_multisnat_init);
  89. module_exit(ipt_multisnat_fini);
libipt_netdnat.c
  1. /* Shared library add-on to iptables to add NETDNAT support.
  2.  *
  3.  * (C) 2011 by liutingwei
  4.  * 2011-02-24 11:28:08
  5.  *
  6.  * This software is released under the terms of GNU GPL
  7.  *
  8.  */
  9. #include <stdio.h>
  10. #include <netdb.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <syslog.h>
  14. #include <getopt.h>
  15. #include <iptables.h>
  16. #include <linux/netfilter_ipv4/ip_tables.h>
  17. #include <linux/netfilter/x_tables.h>
  18. #include "ipt_NETDNAT.h"
  19. #define IPTABLES_VERSION "1.4.0"
  20. enum{
  21.  NETDNAT =1<<0,
  22. };
  23. static void NETDNAT_check(unsigned int flags)
  24. {
  25.  if((flags&NETDNAT)==0)
  26.   //== priority is higher than &

  27.   exit_error(PARAMETER_PROBLEM,"NETDNAT target: You must specify --netdnat");
  28. }
  29. /* Function which prints out usage message. */
  30. static void NETDNAT_help(void)
  31. {
  32.  printf("NETDNAT[LTW] v%s options:\n"
  33.       "--netdnat source-dest\n"
  34.    "\n"
  35.    ,IPTABLES_VERSION);
  36. }
  37. static const struct option NETDNAT_opts[] = {
  38.  {"netdnat", 1, NULL, '1'},
  39.  {NULL,0,NULL,0}
  40. };
  41. /* Function which parses command options; returns true if it
  42.    ate an option */
  43. static int NETDNAT_parse(int c, char **argv, int invert, unsigned int *flags,
  44.                       const void *entry, struct xt_entry_target **target)
  45. {
  46.  char *temp,*tempnet,*p,*n;
  47.  unsigned int sourceip;
  48.  unsigned int destip;
  49.  int mask1,mask2;
  50.  struct ipt_NETDNAT_info *info = (struct ipt_NETDNAT_info *) (*target)->data;
  51.  switch (c) {
  52.   case '1':
  53.    if (*flags&NETDNAT)
  54.     exit_error(PARAMETER_PROBLEM,
  55.       "Can't specify --netdnat twice");
  56.    *flags|=NETDNAT;
  57.    if(strlen(optarg)>37)
  58.     exit_error(PARAMETER_PROBLEM,
  59.       "\"%s\" is not a valid netdnat");
  60.    memcpy(info->netdnat,optarg,strlen(optarg));
  61.    temp=strdup(optarg);
  62.    tempnet=temp;
  63.    n=strchr(tempnet,'-');
  64.    if(n==NULL||(n+1)==NULL)
  65.     exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netdnat");
  66.    *n++=0;
  67.    p=strchr(tempnet,'/');
  68.    if(p==NULL||(p+1)==NULL)
  69.     exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netdnat");
  70.    *p++=0;
  71.    mask1=atoi(p);
  72.    sourceip=inet_network(tempnet);
  73.    tempnet=n;
  74.    p=strchr(tempnet,'/');
  75.    if(p==NULL||(p+1)==NULL)
  76.     exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netdnat");
  77.    *p++=0;
  78.    mask2=atoi(p);
  79.    destip=inet_network(tempnet);
  80.    if(mask1!=mask2)
  81.     exit_error(PARAMETER_PROBLEM,
  82.       "Source and Dest net mask not equeal");
  83.    if(mask1<0||mask1>32)
  84.     exit_error(PARAMETER_PROBLEM,
  85.       "Source and Dest net mask not valid (0-32)");
  86.    if(sourceip==(unsigned int)(-1) || destip==(unsigned int)(-1))
  87.     exit_error(PARAMETER_PROBLEM,
  88.       "Source or Dest ip not valid");
  89.    mask2=32-mask1;
  90.    sourceip=sourceip&~((1<<mask2)-1);
  91.    destip=destip&~((1<<mask2)-1);
  92.    if(sourceip<destip){
  93.     info->flag=1;
  94.     info->excursion=destip-sourceip;
  95.    }else{
  96.     info->flag=0;
  97.     info->excursion=sourceip-destip;
  98.    }
  99.    free(temp);
  100.    break;
  101.   default:
  102.    return 0;
  103.  }
  104.  return 1;
  105. }
  106. /* Saves the union ipt_targinfo in parsable form to stdout. */
  107. static void NETDNAT_save(const void *ip, const struct xt_entry_target *target)
  108. {
  109.  return;
  110. }
  111. static void NETDNAT_init(struct xt_entry_target *t)
  112. {
  113.  struct ipt_NETDNAT_info *info = (struct ipt_NETDNAT_info *) t->data;
  114.  info->flag=-1;
  115.  memset(info->netdnat,0,41);
  116.  return;
  117. }
  118. /* Prints out the targinfo. */
  119. static void NETDNAT_print(const void *ip, const struct xt_entry_target *target,
  120.                        int numeric)
  121. {
  122.  const struct ipt_NETDNAT_info *info
  123.      = (const struct ipt_NETDNAT_info *) target->data;
  124.  printf(" NETDNAT %s ", info->netdnat);
  125. }
  126. static struct iptables_target NETDNAT_target = {
  127.  .name = "NETDNAT",
  128.  .version = IPTABLES_VERSION,
  129.  .size = IPT_ALIGN(sizeof(struct ipt_NETDNAT_info)),
  130.  .userspacesize = IPT_ALIGN(sizeof(struct ipt_NETDNAT_info)),
  131.  .help = NETDNAT_help,
  132.  .parse = NETDNAT_parse,
  133.  .init = NETDNAT_init,
  134.  .final_check= NETDNAT_check,
  135.  .print = NETDNAT_print,
  136.  .save = NETDNAT_save,
  137.  .extra_opts =NETDNAT_opts,
  138. };
  139. void _init(void)
  140. {
  141.  register_target(&NETDNAT_target);
  142. }
阅读(102147) | 评论(9) | 转发(2) |
给主人留下些什么吧!~~

youyunyehe0072012-06-01 09:45:51

很是经典!学习了。有个问题想请教下博主: 现在在市面上有许多路由器支持:
PC机IP、网关、DNS地址任意配,只要插入LAN口,就可以上网。这是怎么实现的, 感觉应该首先做SNAT,但不清晰,PC机IP、 网关、 DNS的ip怎么处理呀?很糊涂,特向博主请教下!

lujian198619862011-11-04 17:13:37

瀚海书香: 比如公网地址到公网地址的转换
18.45.9.0/24-->18.45.12.0/24

内网地址到内网地址的转换:
192.168.0.0/24-->10.0.0.0/24

这种用途在做VPN的时候,是经.....
哦,用在vpn,牛~

lujian198619862011-11-04 17:12:01

回复评论看不到了

瀚海书香2011-11-04 16:25:35

lujian19861986: 你所说的意思是否是 一个wan口分配了多个ip, 我觉得到了wan口就跑POSTROUTING规则,但是之前就过了路由表。找到对应的wan口后做网段的一一对应转换,除非wan口.....
比如公网地址到公网地址的转换
18.45.9.0/24-->18.45.12.0/24

内网地址到内网地址的转换:
192.168.0.0/24-->10.0.0.0/24

这种用途在做VPN的时候,是经常用到的。

lujian198619862011-11-03 09:00:34

瀚海书香: MASQUERAED是无法实现网段地址转换的。
比如将192.168.0.0/24按一一对应的关系转换成172.16.5.0/24

192.168.0.1-->172.16.5.1
192.168.0.86-->172.16.5......
你所说的意思是否是 一个wan口分配了多个ip, 我觉得到了wan口就跑POSTROUTING规则,但是之前就过了路由表。找到对应的wan口后做网段的一一对应转换,除非wan口有ISP分配多个ip