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
- #ifndef _IPT_NETSNAT_H_target
- #define _IPT_NETSNAT_H_target
- struct ipt_NETSNAT_info{
- char netsnat[41];
- unsigned int excursion;
- int flag;//flag=1 means destnet is big than sourcenet;
- //flag=0 means destnet is small than sourcenet.
- };
- #endif
ipt_NETSNAT.c
- /* Netfilter Target NETSNAT
- *
- * (C) 2011 by liutingwei
- * 2011-02-24 09:34:25
- *
- * This software is released under the terms of GNU GPL
- *
- */
- #include <linux/module.h>
- #include <linux/skbuff.h>
- #include <linux/ip.h>
- #include <linux/inet.h>
- #include <linux/netfilter_ipv4/ip_tables.h>
- #include <linux/types.h>
- #include <linux/if.h>
- #include <linux/inetdevice.h>
- #include <net/protocol.h>
- #include <net/checksum.h>
- #include <linux/netfilter_ipv4.h>
- #include <net/netfilter/nf_nat_rule.h>
- #include <net/netfilter/nf_nat_core.h>
- #include "ipt_NETSNAT.h"
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("LTW ");
- MODULE_DESCRIPTION("iptables net snat");
- static bool
- redirect_check(const char *tablename,
- const void *e,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
- {
- return true;
- }
- static unsigned int
- netsnat_target(struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const struct xt_target *target,
- const void *targinfo)
- {
- struct nf_conn *ct;
- struct nf_conn_nat *nat;
- enum ip_conntrack_info ctinfo;
- struct nf_nat_range newrange;
- const struct ipt_NETSNAT_info *info=targinfo;
- struct iphdr *iph;
- __be32 sourceip;
- __be32 newsrc;
- iph=ip_hdr(skb);
- sourceip=ntohl(iph->saddr);
- NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
- ct = nf_ct_get(skb, &ctinfo);
- nat = nfct_nat(ct);
- NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
- || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
- /* Source address is 0.0.0.0 - locally generated packet that is
- * probably not supposed to be masqueraded.
- */
- if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
- return NF_ACCEPT;
- if(info->flag==1)
- newsrc=htonl(sourceip+info->excursion);
- else if(info->flag==0)
- newsrc=htonl(sourceip-info->excursion);
- else
- return NF_ACCEPT;
- /* Transfer from original range. */
- memset(&newrange,0,sizeof(newrange));
- newrange.flags|=IP_NAT_RANGE_MAP_IPS;
- newrange.min_ip=newrange.max_ip=newsrc;
- /* Hand modified range to generic setup. */
- return nf_nat_setup_info(ct, &newrange, hooknum);
- }
- static struct xt_target netsnat_reg __read_mostly = {
- .name = "NETSNAT",
- .family = AF_INET,
- .target = netsnat_target,
- .targetsize = sizeof(struct ipt_NETSNAT_info),
- .table = "nat",
- .hooks = (1 << NF_IP_POST_ROUTING),
- .checkentry = redirect_check,
- .me = THIS_MODULE,
- };
- static int __init ipt_multisnat_init(void)
- {
- return xt_register_target(&netsnat_reg);
- }
- static void __exit ipt_multisnat_fini(void)
- {
- xt_unregister_target(&netsnat_reg);
- }
- module_init(ipt_multisnat_init);
- module_exit(ipt_multisnat_fini);
libipt_netsnat.c
- /* Shared library add-on to iptables to add NETSNAT support.
- *
- * (C) 2011 by liutingwei
- * 2011-02-24 10:20:25
- *
- * This software is released under the terms of GNU GPL
- *
- */
- #include <stdio.h>
- #include <netdb.h>
- #include <string.h>
- #include <stdlib.h>
- #include <syslog.h>
- #include <getopt.h>
- #include <iptables.h>
- #include <linux/netfilter_ipv4/ip_tables.h>
- #include <linux/netfilter/x_tables.h>
- #include "ipt_NETSNAT.h"
- #define IPTABLES_VERSION "1.4.0"
- enum{
- NETSNAT =1<<0,
- };
- static void NETSNAT_check(unsigned int flags)
- {
- if((flags&NETSNAT)==0)
- //== priority is higher than &
- exit_error(PARAMETER_PROBLEM,"NETSNAT target: You must specify --netsnat");
- }
- /* Function which prints out usage message. */
- static void NETSNAT_help(void)
- {
- printf("NETSNAT[LTW] v%s options:\n"
- "--netsnat source-dest\n"
- "\n"
- ,IPTABLES_VERSION);
- }
- static const struct option NETSNAT_opts[] = {
- {"netsnat", 1, NULL, '1'},
- {NULL,0,NULL,0}
- };
- /* Function which parses command options; returns true if it
- ate an option */
- static int NETSNAT_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
- {
- char *temp,*tempnet,*p,*n;
- unsigned int sourceip;
- unsigned int destip;
- int mask1,mask2;
- struct ipt_NETSNAT_info *info = (struct ipt_NETSNAT_info *) (*target)->data;
- switch (c) {
- case '1':
- if (*flags&NETSNAT)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify --netsnat twice");
- *flags|=NETSNAT;
- if(strlen(optarg)>37)
- exit_error(PARAMETER_PROBLEM,
- "\"%s\" is not a valid netsnat");
- memcpy(info->netsnat,optarg,strlen(optarg));
- temp=strdup(optarg);
- tempnet=temp;
- n=strchr(tempnet,'-');
- if(n==NULL||(n+1)==NULL)
- exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netsnat");
- *n++=0;
- p=strchr(tempnet,'/');
- if(p==NULL||(p+1)==NULL)
- exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netsnat");
- *p++=0;
- mask1=atoi(p);
- sourceip=inet_network(tempnet);
- tempnet=n;
- p=strchr(tempnet,'/');
- if(p==NULL||(p+1)==NULL)
- exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netsnat");
- *p++=0;
- mask2=atoi(p);
- destip=inet_network(tempnet);
- if(mask1!=mask2)
- exit_error(PARAMETER_PROBLEM,
- "Source and Dest net mask not equeal");
- if(mask1<0||mask1>32)
- exit_error(PARAMETER_PROBLEM,
- "Source and Dest net mask not valid (0-32)");
- if(sourceip==(unsigned int)(-1) || destip==(unsigned int)(-1))
- exit_error(PARAMETER_PROBLEM,
- "Source or Dest ip not valid");
- mask2=32-mask1;
- sourceip=sourceip&~((1<<mask2)-1);
- destip=destip&~((1<<mask2)-1);
- if(sourceip<destip){
- info->flag=1;
- info->excursion=destip-sourceip;
- }else{
- info->flag=0;
- info->excursion=sourceip-destip;
- }
- free(temp);
- break;
- default:
- return 0;
- }
- return 1;
- }
- /* Saves the union ipt_targinfo in parsable form to stdout. */
- static void NETSNAT_save(const void *ip, const struct xt_entry_target *target)
- {
- return;
- }
- static void NETSNAT_init(struct xt_entry_target *t)
- {
- struct ipt_NETSNAT_info *info = (struct ipt_NETSNAT_info *) t->data;
- info->flag=-1;
- memset(info->netsnat,0,41);
- return;
- }
- /* Prints out the targinfo. */
- static void NETSNAT_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
- {
- const struct ipt_NETSNAT_info *info
- = (const struct ipt_NETSNAT_info *) target->data;
- printf(" NETSNAT %s ", info->netsnat);
- }
- static struct iptables_target NETSNAT_target = {
- .name = "NETSNAT",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_NETSNAT_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_NETSNAT_info)),
- .help = NETSNAT_help,
- .parse = NETSNAT_parse,
- .init = NETSNAT_init,
- .final_check= NETSNAT_check,
- .print = NETSNAT_print,
- .save = NETSNAT_save,
- .extra_opts =NETSNAT_opts,
- };
- void _init(void)
- {
- register_target(&NETSNAT_target);
- }
ipt_netdnat.h
- #ifndef _IPT_NETDNAT_H_target
- #define _IPT_NETDNAT_H_target
- struct ipt_NETDNAT_info{
- char netdnat[41];
- unsigned int excursion;
- int flag;//flag=1 means destnet is big than sourcenet;
- //flag=0 means destnet is small than sourcenet.
- };
- #endif
ipt_netdnat.c
- /* Netfilter NETDNAT Target
- *
- * (C) 2011 by liutingwei
- * 2011-02-24 11:02:47
- *
- * This software is released under the terms of GNU GPL
- *
- */
- #include <linux/module.h>
- #include <linux/skbuff.h>
- #include <linux/ip.h>
- #include <linux/inet.h>
- #include <linux/netfilter_ipv4/ip_tables.h>
- #include <linux/types.h>
- #include <linux/if.h>
- #include <linux/inetdevice.h>
- #include <net/protocol.h>
- #include <net/checksum.h>
- #include <linux/netfilter_ipv4.h>
- #include <net/netfilter/nf_nat_rule.h>
- #include <net/netfilter/nf_nat_core.h>
- #include "ipt_NETDNAT.h"
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("LTW ");
- MODULE_DESCRIPTION("iptables net snat");
- static bool
- redirect_check(const char *tablename,
- const void *e,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
- {
- return true;
- }
- static unsigned int
- netdnat_target(struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const struct xt_target *target,
- const void *targinfo)
- {
- struct nf_conn *ct;
- struct nf_conn_nat *nat;
- enum ip_conntrack_info ctinfo;
- struct nf_nat_range newrange;
- const struct ipt_NETDNAT_info *info=targinfo;
- struct iphdr *iph;
- __be32 destip;
- __be32 newdest;
- iph=ip_hdr(skb);
- destip=ntohl(iph->daddr);
- NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING);
- ct = nf_ct_get(skb, &ctinfo);
- nat = nfct_nat(ct);
- NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
- if(info->flag==1)
- newdest=htonl(destip+info->excursion);
- else if(info->flag==0)
- newdest=htonl(destip-info->excursion);
- else
- return NF_ACCEPT;
- /* Transfer from original range. */
- memset(&newrange,0,sizeof(newrange));
- newrange.flags|=IP_NAT_RANGE_MAP_IPS;
- newrange.min_ip=newrange.max_ip=newdest;
- /* Hand modified range to generic setup. */
- return nf_nat_setup_info(ct, &newrange, hooknum);
- }
- static struct xt_target netdnat_reg __read_mostly = {
- .name = "NETDNAT",
- .family = AF_INET,
- .target = netdnat_target,
- .targetsize = sizeof(struct ipt_NETDNAT_info),
- .table = "nat",
- .hooks = (1 << NF_IP_PRE_ROUTING),
- .checkentry = redirect_check,
- .me = THIS_MODULE,
- };
- static int __init ipt_multisnat_init(void)
- {
- return xt_register_target(&netdnat_reg);
- }
- static void __exit ipt_multisnat_fini(void)
- {
- xt_unregister_target(&netdnat_reg);
- }
- module_init(ipt_multisnat_init);
- module_exit(ipt_multisnat_fini);
libipt_netdnat.c
- /* Shared library add-on to iptables to add NETDNAT support.
- *
- * (C) 2011 by liutingwei
- * 2011-02-24 11:28:08
- *
- * This software is released under the terms of GNU GPL
- *
- */
- #include <stdio.h>
- #include <netdb.h>
- #include <string.h>
- #include <stdlib.h>
- #include <syslog.h>
- #include <getopt.h>
- #include <iptables.h>
- #include <linux/netfilter_ipv4/ip_tables.h>
- #include <linux/netfilter/x_tables.h>
- #include "ipt_NETDNAT.h"
- #define IPTABLES_VERSION "1.4.0"
- enum{
- NETDNAT =1<<0,
- };
- static void NETDNAT_check(unsigned int flags)
- {
- if((flags&NETDNAT)==0)
- //== priority is higher than &
- exit_error(PARAMETER_PROBLEM,"NETDNAT target: You must specify --netdnat");
- }
- /* Function which prints out usage message. */
- static void NETDNAT_help(void)
- {
- printf("NETDNAT[LTW] v%s options:\n"
- "--netdnat source-dest\n"
- "\n"
- ,IPTABLES_VERSION);
- }
- static const struct option NETDNAT_opts[] = {
- {"netdnat", 1, NULL, '1'},
- {NULL,0,NULL,0}
- };
- /* Function which parses command options; returns true if it
- ate an option */
- static int NETDNAT_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
- {
- char *temp,*tempnet,*p,*n;
- unsigned int sourceip;
- unsigned int destip;
- int mask1,mask2;
- struct ipt_NETDNAT_info *info = (struct ipt_NETDNAT_info *) (*target)->data;
- switch (c) {
- case '1':
- if (*flags&NETDNAT)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify --netdnat twice");
- *flags|=NETDNAT;
- if(strlen(optarg)>37)
- exit_error(PARAMETER_PROBLEM,
- "\"%s\" is not a valid netdnat");
- memcpy(info->netdnat,optarg,strlen(optarg));
- temp=strdup(optarg);
- tempnet=temp;
- n=strchr(tempnet,'-');
- if(n==NULL||(n+1)==NULL)
- exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netdnat");
- *n++=0;
- p=strchr(tempnet,'/');
- if(p==NULL||(p+1)==NULL)
- exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netdnat");
- *p++=0;
- mask1=atoi(p);
- sourceip=inet_network(tempnet);
- tempnet=n;
- p=strchr(tempnet,'/');
- if(p==NULL||(p+1)==NULL)
- exit_error(PARAMETER_PROBLEM,"\"%s\" is not a valid netdnat");
- *p++=0;
- mask2=atoi(p);
- destip=inet_network(tempnet);
- if(mask1!=mask2)
- exit_error(PARAMETER_PROBLEM,
- "Source and Dest net mask not equeal");
- if(mask1<0||mask1>32)
- exit_error(PARAMETER_PROBLEM,
- "Source and Dest net mask not valid (0-32)");
- if(sourceip==(unsigned int)(-1) || destip==(unsigned int)(-1))
- exit_error(PARAMETER_PROBLEM,
- "Source or Dest ip not valid");
- mask2=32-mask1;
- sourceip=sourceip&~((1<<mask2)-1);
- destip=destip&~((1<<mask2)-1);
- if(sourceip<destip){
- info->flag=1;
- info->excursion=destip-sourceip;
- }else{
- info->flag=0;
- info->excursion=sourceip-destip;
- }
- free(temp);
- break;
- default:
- return 0;
- }
- return 1;
- }
- /* Saves the union ipt_targinfo in parsable form to stdout. */
- static void NETDNAT_save(const void *ip, const struct xt_entry_target *target)
- {
- return;
- }
- static void NETDNAT_init(struct xt_entry_target *t)
- {
- struct ipt_NETDNAT_info *info = (struct ipt_NETDNAT_info *) t->data;
- info->flag=-1;
- memset(info->netdnat,0,41);
- return;
- }
- /* Prints out the targinfo. */
- static void NETDNAT_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
- {
- const struct ipt_NETDNAT_info *info
- = (const struct ipt_NETDNAT_info *) target->data;
- printf(" NETDNAT %s ", info->netdnat);
- }
- static struct iptables_target NETDNAT_target = {
- .name = "NETDNAT",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_NETDNAT_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_NETDNAT_info)),
- .help = NETDNAT_help,
- .parse = NETDNAT_parse,
- .init = NETDNAT_init,
- .final_check= NETDNAT_check,
- .print = NETDNAT_print,
- .save = NETDNAT_save,
- .extra_opts =NETDNAT_opts,
- };
- void _init(void)
- {
- register_target(&NETDNAT_target);
- }
阅读(2011) | 评论(0) | 转发(0) |