All of lore.kernel.org
 help / color / mirror / Atom feed
* Resend [patch 2/2] iptables: add random option to SNAT
@ 2007-02-05 13:25 Eric Leblond
  2007-02-05 15:06 ` Patrick McHardy
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Leblond @ 2007-02-05 13:25 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Patrick McHardy, Pablo Neira Ayuso


[-- Attachment #1.1: Type: text/plain, Size: 311 bytes --]

Hi,

This is a resend of :
	http://patchwork.netfilter.org/netfilter-devel/patch.pl?id=36

Merge window for 2.6.21 is open and kernel part of the feature should
reach kernel tree soon...

BR,
-- 
Éric Leblond, eleblond@inl.fr
Téléphone : 01 44 89 46 39, Fax : 01 44 89 45 01
INL, http://www.inl.fr

[-- Attachment #1.2: iptables-random-nat.diff --]
[-- Type: text/x-patch, Size: 7534 bytes --]

Index: extensions/libipt_MASQUERADE.c
===================================================================
--- extensions/libipt_MASQUERADE.c	(révision 6735)
+++ extensions/libipt_MASQUERADE.c	(copie de travail)
@@ -14,7 +14,7 @@
 {
 	printf(
 "MASQUERADE v%s options:\n"
-" --to-ports <port>[-<port>]\n"
+" --to-ports [<port>[-<port>]][:random]\n"
 "				Port (range) to map to.\n\n",
 IPTABLES_VERSION);
 }
@@ -40,14 +40,30 @@
 parse_ports(const char *arg, struct ip_nat_multi_range *mr)
 {
 	const char *dash;
+	char *random;
 	int port;
 
+	if (*arg == 'r'){
+		mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		return;
+	}
+
 	mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 
 	port = atoi(arg);
 	if (port <= 0 || port > 65535)
 		exit_error(PARAMETER_PROBLEM, "Port `%s' not valid\n", arg);
 
+	random = strchr(arg, ':');
+	if (random) {
+		if (*(random+1) == 'r') {
+			mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+			*random = '\0';
+		} else {
+			exit_error(PARAMETER_PROBLEM, "Random specification `%s' not valid\n", arg);
+		}
+	}
+
 	dash = strchr(arg, '-');
 	if (!dash) {
 		mr->range[0].min.tcp.port
@@ -125,8 +141,11 @@
 		printf("%hu", ntohs(r->min.tcp.port));
 		if (r->max.tcp.port != r->min.tcp.port)
 			printf("-%hu", ntohs(r->max.tcp.port));
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random");
 		printf(" ");
-	}
+	} else if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		printf("random ");
 }
 
 /* Saves the union ipt_targinfo in parsable form to stdout. */
@@ -141,8 +160,11 @@
 		printf("--to-ports %hu", ntohs(r->min.tcp.port));
 		if (r->max.tcp.port != r->min.tcp.port)
 			printf("-%hu", ntohs(r->max.tcp.port));
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random");
 		printf(" ");
-	}
+	} else if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		printf("--to-ports random ");
 }
 
 static struct iptables_target masq = { NULL,
Index: extensions/libipt_SNAT.c
===================================================================
--- extensions/libipt_SNAT.c	(révision 6735)
+++ extensions/libipt_SNAT.c	(copie de travail)
@@ -22,9 +22,11 @@
 {
 	printf(
 "SNAT v%s options:\n"
-" --to-source <ipaddr>[-<ipaddr>][:port-port]\n"
+" --to-source <ipaddr>[-<ipaddr>][:port-port][:random]\n"
 "				Address to map source to.\n"
-"				(You can use this more than once)\n\n",
+"				(You can use this more than once)\n"
+"				random adds randomness in port selection\n"
+"				to avoid attack by port prediction\n",
 IPTABLES_VERSION);
 }
 
@@ -57,7 +59,7 @@
 parse_to(char *arg, int portok, struct ipt_natinfo *info)
 {
 	struct ip_nat_range range;
-	char *colon, *dash, *error;
+	char *colon, *dash, *random;
 	struct in_addr *ip;
 
 	memset(&range, 0, sizeof(range));
@@ -66,44 +68,55 @@
 	if (colon) {
 		int port;
 
-		if (!portok)
-			exit_error(PARAMETER_PROBLEM,
-				   "Need TCP or UDP with port specification");
+		if (*(colon+1) == 'r') {
+			/* syntax is IP1-IP2:R we just set random */
+			range.flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		} else {
+			if (!portok)
+				exit_error(PARAMETER_PROBLEM,
+						"Need TCP or UDP with port specification");
 
-		range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+			range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 
-		port = atoi(colon+1);
-		if (port <= 0 || port > 65535)
-			exit_error(PARAMETER_PROBLEM,
-				   "Port `%s' not valid\n", colon+1);
+			port = atoi(colon+1);
+			if (port <= 0 || port > 65535)
+				exit_error(PARAMETER_PROBLEM,
+						"Port `%s' not valid\n", colon+1);
 
-		error = strchr(colon+1, ':');
-		if (error)
-			exit_error(PARAMETER_PROBLEM,
-				   "Invalid port:port syntax - use dash\n");
+			random = strchr(colon+1, ':');
+			if (random) {
+				if (*(random+1) != 'r'){
+				exit_error(PARAMETER_PROBLEM,
+						"Invalid port:port syntax - use dash\n");
+				} else {
+					range.flags |= IP_NAT_RANGE_PROTO_RANDOM;
+					*random = '\0';
+				}
+			}
 
-		dash = strchr(colon, '-');
-		if (!dash) {
-			range.min.tcp.port
-				= range.max.tcp.port
-				= htons(port);
-		} else {
-			int maxport;
+			dash = strchr(colon, '-');
+			if (!dash) {
+				range.min.tcp.port
+					= range.max.tcp.port
+					= htons(port);
+			} else {
+				int maxport;
 
-			maxport = atoi(dash + 1);
-			if (maxport <= 0 || maxport > 65535)
-				exit_error(PARAMETER_PROBLEM,
-					   "Port `%s' not valid\n", dash+1);
-			if (maxport < port)
-				/* People are stupid. */
-				exit_error(PARAMETER_PROBLEM,
-					   "Port range `%s' funky\n", colon+1);
-			range.min.tcp.port = htons(port);
-			range.max.tcp.port = htons(maxport);
+				maxport = atoi(dash + 1);
+				if (maxport <= 0 || maxport > 65535)
+					exit_error(PARAMETER_PROBLEM,
+							"Port `%s' not valid\n", dash+1);
+				if (maxport < port)
+					/* People are stupid. */
+					exit_error(PARAMETER_PROBLEM,
+							"Port range `%s' funky\n", colon+1);
+				range.min.tcp.port = htons(port);
+				range.max.tcp.port = htons(maxport);
+			}
+			/* Starts with a colon? No IP info...*/
+			if (colon == arg)
+				return &(append_range(info, &range)->t);
 		}
-		/* Starts with a colon? No IP info...*/
-		if (colon == arg)
-			return &(append_range(info, &range)->t);
 		*colon = '\0';
 	}
 
@@ -197,6 +210,9 @@
 		if (r->max.tcp.port != r->min.tcp.port)
 			printf("-%hu", ntohs(r->max.tcp.port));
 	}
+	if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		printf(":random");
+	}
 }
 
 /* Prints out the targinfo. */
Index: extensions/libipt_SAME.c
===================================================================
--- extensions/libipt_SAME.c	(révision 6735)
+++ extensions/libipt_SAME.c	(copie de travail)
@@ -16,7 +16,7 @@
 {
 	printf(
 "SAME v%s options:\n"
-" --to <ipaddr>-<ipaddr>\n"
+" --to <ipaddr>-<ipaddr>[:random]\n"
 "				Addresses to map source to.\n"
 "				 May be specified more than\n"
 "				  once for multiple ranges.\n"
@@ -49,10 +49,21 @@
 static void
 parse_to(char *arg, struct ip_nat_range *range)
 {
-	char *dash;
+	char *dash, *random;
 	struct in_addr *ip;
 
 	range->flags |= IP_NAT_RANGE_MAP_IPS;
+
+	random = strchr(arg, ':');
+	if (random) {
+		if (*(random+1) == 'r') {
+			range->flags |= IP_NAT_RANGE_PROTO_RANDOM;
+			*random = '\0';
+		} else {
+			exit_error(PARAMETER_PROBLEM, "Random specification `%s' not valid\n", random+1);
+		}
+	}
+
 	dash = strchr(arg, '-');
 
 	if (dash)
@@ -90,7 +101,7 @@
 	struct ipt_same_info *mr
 		= (struct ipt_same_info *)(*target)->data;
 
-	switch (c) {
+switch (c) {
 	case '1':
 		if (mr->rangesize == IPT_SAME_MAX_RANGE)
 			exit_error(PARAMETER_PROBLEM,
@@ -151,10 +162,13 @@
 		printf("%s", addr_to_dotted(&a));
 		a.s_addr = r->max_ip;
 		
-		if (r->min_ip == r->max_ip)
+		if (r->min_ip != r->max_ip)
+			printf("-%s", addr_to_dotted(&a));
+
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random ");
+		else
 			printf(" ");
-		else
-			printf("-%s ", addr_to_dotted(&a));
 	}
 	
 	if (mr->info & IPT_SAME_NODST)
@@ -177,10 +191,13 @@
 		printf("--to %s", addr_to_dotted(&a));
 		a.s_addr = r->max_ip;
 
-		if (r->min_ip == r->max_ip)
+		if (r->min_ip != r->max_ip)
+			printf("-%s", addr_to_dotted(&a));
+
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random ");
+		else
 			printf(" ");
-		else
-			printf("-%s ", addr_to_dotted(&a));
 	}
 	
 	if (mr->info & IPT_SAME_NODST)

[-- Attachment #2: Ceci est une partie de message numériquement signée --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Resend [patch 2/2] iptables: add random option to SNAT
  2007-02-05 13:25 Resend [patch 2/2] iptables: add random option to SNAT Eric Leblond
@ 2007-02-05 15:06 ` Patrick McHardy
  2007-02-05 15:55   ` Eric Leblond
  0 siblings, 1 reply; 9+ messages in thread
From: Patrick McHardy @ 2007-02-05 15:06 UTC (permalink / raw)
  To: Eric Leblond; +Cc: netfilter-devel, Pablo Neira Ayuso

Eric Leblond wrote:
> Hi,
> 
> This is a resend of :
> 	http://patchwork.netfilter.org/netfilter-devel/patch.pl?id=36
> 
> Merge window for 2.6.21 is open and kernel part of the feature should
> reach kernel tree soon...


I'm in the process of preparing my patches for upstream submission
(which include your random patch). I'll look into the userspace patch
after that, I'm not a big fan of the :random syntax.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Resend [patch 2/2] iptables: add random option to SNAT
  2007-02-05 15:06 ` Patrick McHardy
@ 2007-02-05 15:55   ` Eric Leblond
  2007-02-12 13:40     ` Patrick McHardy
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Leblond @ 2007-02-05 15:55 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, Pablo Neira Ayuso

[-- Attachment #1: Type: text/plain, Size: 686 bytes --]

Hi,

Le lundi 05 février 2007 à 16:06 +0100, Patrick McHardy a écrit :
> Eric Leblond wrote:
> I'm in the process of preparing my patches for upstream submission
> (which include your random patch).

Great.

> I'll look into the userspace patch
> after that, I'm not a big fan of the :random syntax.

I make this choice because iptables had the capabilities to have
multiple NAT ranges and hence randomization has to be linked with the
range.

But we can also assume to have a per iptables rule switch. I can rewrite
my patch in this way if you want.

BR,
-- 
Éric Leblond, eleblond@inl.fr
Téléphone : 01 44 89 46 39, Fax : 01 44 89 45 01
INL, http://www.inl.fr

[-- Attachment #2: Ceci est une partie de message numériquement signée --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Resend [patch 2/2] iptables: add random option to SNAT
  2007-02-05 15:55   ` Eric Leblond
@ 2007-02-12 13:40     ` Patrick McHardy
  2007-02-12 18:38       ` Jan Engelhardt
  2007-02-24 14:10       ` Eric Leblond
  0 siblings, 2 replies; 9+ messages in thread
From: Patrick McHardy @ 2007-02-12 13:40 UTC (permalink / raw)
  To: Eric Leblond; +Cc: netfilter-devel, Pablo Neira Ayuso

Eric Leblond wrote:
>>I'll look into the userspace patch
>>after that, I'm not a big fan of the :random syntax.
> 
> 
> I make this choice because iptables had the capabilities to have
> multiple NAT ranges and hence randomization has to be linked with the
> range.

Not anymore since since rustynat changes (~2.6.12).

> 
> But we can also assume to have a per iptables rule switch. I can rewrite
> my patch in this way if you want.

I think I would prefer that.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Resend [patch 2/2] iptables: add random option to SNAT
  2007-02-12 13:40     ` Patrick McHardy
@ 2007-02-12 18:38       ` Jan Engelhardt
  2007-02-12 19:38         ` Patrick McHardy
  2007-02-24 14:10       ` Eric Leblond
  1 sibling, 1 reply; 9+ messages in thread
From: Jan Engelhardt @ 2007-02-12 18:38 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, Pablo Neira Ayuso, Eric Leblond


On Feb 12 2007 14:40, Patrick McHardy wrote:
>Eric Leblond wrote:
>>>I'll look into the userspace patch
>>>after that, I'm not a big fan of the :random syntax.
>> 
>> 
>> I make this choice because iptables had the capabilities to have
>> multiple NAT ranges and hence randomization has to be linked with the
>> range.
>
>Not anymore since since rustynat changes (~2.6.12).

So what's the proper way to do that then?


Jan
-- 
ft: http://freshmeat.net/p/chaostables/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Resend [patch 2/2] iptables: add random option to SNAT
  2007-02-12 18:38       ` Jan Engelhardt
@ 2007-02-12 19:38         ` Patrick McHardy
  0 siblings, 0 replies; 9+ messages in thread
From: Patrick McHardy @ 2007-02-12 19:38 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netfilter-devel, Pablo Neira Ayuso, Eric Leblond

Jan Engelhardt wrote:
> On Feb 12 2007 14:40, Patrick McHardy wrote:
> 
>>Eric Leblond wrote:
>>
>>>I make this choice because iptables had the capabilities to have
>>>multiple NAT ranges and hence randomization has to be linked with the
>>>range.
>>
>>Not anymore since since rustynat changes (~2.6.12).
> 
> 
> So what's the proper way to do that then?


There is none, nobody was using it.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Resend [patch 2/2] iptables: add random option to SNAT
  2007-02-12 13:40     ` Patrick McHardy
  2007-02-12 18:38       ` Jan Engelhardt
@ 2007-02-24 14:10       ` Eric Leblond
  2007-02-24 14:21         ` Patrick McHardy
  1 sibling, 1 reply; 9+ messages in thread
From: Eric Leblond @ 2007-02-24 14:10 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel, Pablo Neira Ayuso


[-- Attachment #1.1: Type: text/plain, Size: 434 bytes --]

Hi,

Le lundi 12 février 2007 à 14:40 +0100, Patrick McHardy a écrit :
> > But we can also assume to have a per iptables rule switch. I can rewrite
> > my patch in this way if you want.
> 
> I think I would prefer that.

Here's the corresponding patch. It adds a --random flags to SNAT, SAME
and MASQUERADE targets.

I've also updated man pages by adding this --random option.

BR,
-- 
Eric Leblond <eric@inl.fr>
INL

[-- Attachment #1.2: iptables-randomize-port.diff --]
[-- Type: text/x-patch, Size: 8484 bytes --]

Index: extensions/libipt_MASQUERADE.c
===================================================================
--- extensions/libipt_MASQUERADE.c	(révision 6752)
+++ extensions/libipt_MASQUERADE.c	(copie de travail)
@@ -15,12 +15,21 @@
 	printf(
 "MASQUERADE v%s options:\n"
 " --to-ports <port>[-<port>]\n"
-"				Port (range) to map to.\n\n",
+"				Port (range) to map to.\n"
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+" --random\n"
+"				Randomize source port.\n"
+#endif
+"\n"
+,
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
 	{ "to-ports", 1, 0, '1' },
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	{ "random", 0, 0, '2' },
+#endif
 	{ 0 }
 };
 
@@ -100,6 +109,12 @@
 		parse_ports(optarg, mr);
 		return 1;
 
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	case '2':
+		mr->range[0].flags |=  IP_NAT_RANGE_PROTO_RANDOM;
+		return 1;
+#endif
+
 	default:
 		return 0;
 	}
@@ -127,6 +142,12 @@
 			printf("-%hu", ntohs(r->max.tcp.port));
 		printf(" ");
 	}
+
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		printf("random");
+	}
+#endif
 }
 
 /* Saves the union ipt_targinfo in parsable form to stdout. */
Index: extensions/libipt_SNAT.man
===================================================================
--- extensions/libipt_SNAT.man	(révision 6752)
+++ extensions/libipt_SNAT.man	(copie de travail)
@@ -7,7 +7,7 @@
 mangled), and rules should cease being examined.  It takes one type
 of option:
 .TP
-.BR "--to-source  " "\fIipaddr\fP[-\fIipaddr\fP][:\fIport\fP-\fIport\fP]"
+.BR "--to-source  " "\fIipaddr\fP[-\fIipaddr\fP][:\fIport\fP-\fIport\fP]" [ "--random" ]
 which can specify a single new source IP address, an inclusive range
 of IP addresses, and optionally, a port range (which is only valid if
 the rule also specifies
@@ -17,7 +17,10 @@
 If no port range is specified, then source ports below 512 will be
 mapped to other ports below 512: those between 512 and 1023 inclusive
 will be mapped to ports below 1024, and other ports will be mapped to
-1024 or above. Where possible, no port alteration will occur.
+1024 or above. Where possible, no port alteration will  If option
+.B "--random"
+is used then port mapping will be forcely randomized to avoid
+attacks based on port prediction (kernel >= 2.6.21).
 .RS
 .PP
 In Kernels up to 2.6.10, you can add several --to-source options.  For those
Index: extensions/libipt_SNAT.c
===================================================================
--- extensions/libipt_SNAT.c	(révision 6752)
+++ extensions/libipt_SNAT.c	(copie de travail)
@@ -8,6 +8,11 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 
+#define IPT_SNAT_OPT_SOURCE 0x01
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+#	define IPT_SNAT_OPT_RANDOM 0x02
+#endif
+
 /* Source NAT data consists of a multi-range, indicating where to map
    to. */
 struct ipt_natinfo
@@ -22,7 +27,11 @@
 {
 	printf(
 "SNAT v%s options:\n"
-" --to-source <ipaddr>[-<ipaddr>][:port-port]\n"
+" --to-source <ipaddr>[-<ipaddr>][:port-port]"
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+"[--random]"
+#endif
+"\n"
 "				Address to map source to.\n"
 "				(You can use this more than once)\n\n",
 IPTABLES_VERSION);
@@ -30,6 +39,9 @@
 
 static struct option opts[] = {
 	{ "to-source", 1, 0, '1' },
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	{ "random", 0, 0, '2' },
+#endif
 	{ 0 }
 };
 
@@ -155,7 +167,7 @@
 			exit_error(PARAMETER_PROBLEM,
 				   "Unexpected `!' after --to-source");
 
-		if (*flags) {
+		if (*flags & IPT_SNAT_OPT_SOURCE) {
 			if (!kernel_version)
 				get_kernel_version();
 			if (kernel_version > LINUX_VERSION(2, 6, 10))
@@ -163,9 +175,23 @@
 					   "Multiple --to-source not supported");
 		}
 		*target = parse_to(optarg, portok, info);
-		*flags = 1;
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+		if (*flags & IPT_SNAT_OPT_RANDOM)
+			info->mr.range[0].flags |=  IP_NAT_RANGE_PROTO_RANDOM;
+#endif
+		*flags = IPT_SNAT_OPT_SOURCE;
 		return 1;
 
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	case '2':
+		if (*flags & IPT_SNAT_OPT_SOURCE) {
+			info->mr.range[0].flags |=  IP_NAT_RANGE_PROTO_RANDOM;
+			*flags |= IPT_SNAT_OPT_RANDOM;
+		} else
+			*flags |= IPT_SNAT_OPT_RANDOM;
+		return 1;
+#endif
+
 	default:
 		return 0;
 	}
@@ -174,7 +200,7 @@
 /* Final check; must have specfied --to-source. */
 static void final_check(unsigned int flags)
 {
-	if (!flags)
+	if (!(flags & IPT_SNAT_OPT_SOURCE))
 		exit_error(PARAMETER_PROBLEM,
 			   "You must specify --to-source");
 }
@@ -197,6 +223,11 @@
 		if (r->max.tcp.port != r->min.tcp.port)
 			printf("-%hu", ntohs(r->max.tcp.port));
 	}
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		printf(" random");
+	}
+#endif
 }
 
 /* Prints out the targinfo. */
Index: extensions/libipt_SAME.man
===================================================================
--- extensions/libipt_SAME.man	(révision 6752)
+++ extensions/libipt_SAME.man	(copie de travail)
@@ -9,3 +9,7 @@
 .B "--nodst"
 Don't use the destination-ip in the calculations when selecting the
 new source-ip
+.TP
+.B "--random"
+Port mapping will be forcely randomized to avoid attacks based on 
+port prediction (kernel >= 2.6.21).
Index: extensions/libipt_SAME.c
===================================================================
--- extensions/libipt_SAME.c	(révision 6752)
+++ extensions/libipt_SAME.c	(copie de travail)
@@ -22,13 +22,22 @@
 "				  once for multiple ranges.\n"
 " --nodst\n"
 "				Don't use destination-ip in\n"
-"				           source selection\n",
+"				           source selection\n"
+
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+" --random\n"
+"				Randomize source port\n"
+#endif
+,
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
 	{ "to", 1, 0, '1' },
 	{ "nodst", 0, 0, '2'},
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	{ "random", 0, 0, '3' },
+#endif
 	{ 0 }
 };
 
@@ -79,6 +88,9 @@
 
 #define IPT_SAME_OPT_TO			0x01
 #define IPT_SAME_OPT_NODST		0x02
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+#	define IPT_SAME_OPT_RANDOM		0x04
+#endif
 
 /* Function which parses command options; returns true if it
    ate an option */
@@ -89,6 +101,9 @@
 {
 	struct ipt_same_info *mr
 		= (struct ipt_same_info *)(*target)->data;
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	int count;
+#endif
 
 	switch (c) {
 	case '1':
@@ -102,6 +117,11 @@
 				   "Unexpected `!' after --to");
 
 		parse_to(optarg, &mr->range[mr->rangesize]);
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+		if (*flags & IPT_SAME_OPT_RANDOM)
+			mr->range[mr->rangesize].flags 
+				|= IP_NAT_RANGE_PROTO_RANDOM;
+#endif
 		mr->rangesize++;
 		*flags |= IPT_SAME_OPT_TO;
 		break;
@@ -114,7 +134,14 @@
 		mr->info |= IPT_SAME_NODST;
 		*flags |= IPT_SAME_OPT_NODST;
 		break;
-		
+
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	case '3':	
+		*flags |= IPT_SAME_OPT_RANDOM;
+		for (count=0; count < mr->rangesize; count++)
+			mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		break;
+#endif
 	default:
 		return 0;
 	}
@@ -139,6 +166,9 @@
 	int count;
 	struct ipt_same_info *mr
 		= (struct ipt_same_info *)target->data;
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	int random = 0;
+#endif
 	
 	printf("same:");
 	
@@ -155,10 +185,19 @@
 			printf(" ");
 		else
 			printf("-%s ", addr_to_dotted(&a));
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 
+			random = 1;
+#endif
 	}
 	
 	if (mr->info & IPT_SAME_NODST)
 		printf("nodst ");
+
+#ifdef IP_NAT_RANGE_PROTO_RANDOM
+	if (random)
+		printf("random ");
+#endif
 }
 
 /* Saves the union ipt_targinfo in parsable form to stdout. */
Index: extensions/libipt_MASQUERADE.man
===================================================================
--- extensions/libipt_MASQUERADE.man	(révision 6752)
+++ extensions/libipt_MASQUERADE.man	(copie de travail)
@@ -14,9 +14,19 @@
 .TP
 .BR "--to-ports " "\fIport\fP[-\fIport\fP]"
 This specifies a range of source ports to use, overriding the default
+.TP
+.BR "--random"
+Randomize source port mapping
+.TP
 .B SNAT
 source port-selection heuristics (see above).  This is only valid
 if the rule also specifies
 .B "-p tcp"
 or
 .BR "-p udp" .
+If option
+.B "--random"
+is used then port mapping will be forcely randomized to avoid
+attacks based on port prediction (kernel >= 2.6.21).
+
+

[-- Attachment #2: Ceci est une partie de message numériquement signée --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Resend [patch 2/2] iptables: add random option to SNAT
  2007-02-24 14:10       ` Eric Leblond
@ 2007-02-24 14:21         ` Patrick McHardy
  0 siblings, 0 replies; 9+ messages in thread
From: Patrick McHardy @ 2007-02-24 14:21 UTC (permalink / raw)
  To: Eric Leblond; +Cc: netfilter-devel, Pablo Neira Ayuso

Eric Leblond wrote:
> Here's the corresponding patch. It adds a --random flags to SNAT, SAME
> and MASQUERADE targets.
> 
> I've also updated man pages by adding this --random option.

Applied, thanks Eric.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Resend [Patch 2/2] iptables: add random option to SNAT
  2007-01-12 22:53 ` Jan Engelhardt
@ 2007-01-13 12:06   ` Eric Leblond
  0 siblings, 0 replies; 9+ messages in thread
From: Eric Leblond @ 2007-01-13 12:06 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netfilter-devel


[-- Attachment #1.1: Type: text/plain, Size: 393 bytes --]

Hi,

Thanks for your remarks.

Le vendredi 12 janvier 2007 à 23:53 +0100, Jan Engelhardt a écrit :
> >This patches against kernel and iptables add the capability to randomize
> >the source port used when doing SNAT.
> 
> You might also want to patch MASQUERADE and SAME.

This new patch adds random support to SNAT, MASQUERADE and SAME.

BR,
-- 
Eric Leblond <eric@inl.fr>
INL

[-- Attachment #1.2: iptables-random-nat.diff --]
[-- Type: text/x-patch, Size: 7534 bytes --]

Index: extensions/libipt_MASQUERADE.c
===================================================================
--- extensions/libipt_MASQUERADE.c	(révision 6735)
+++ extensions/libipt_MASQUERADE.c	(copie de travail)
@@ -14,7 +14,7 @@
 {
 	printf(
 "MASQUERADE v%s options:\n"
-" --to-ports <port>[-<port>]\n"
+" --to-ports [<port>[-<port>]][:random]\n"
 "				Port (range) to map to.\n\n",
 IPTABLES_VERSION);
 }
@@ -40,14 +40,30 @@
 parse_ports(const char *arg, struct ip_nat_multi_range *mr)
 {
 	const char *dash;
+	char *random;
 	int port;
 
+	if (*arg == 'r'){
+		mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		return;
+	}
+
 	mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 
 	port = atoi(arg);
 	if (port <= 0 || port > 65535)
 		exit_error(PARAMETER_PROBLEM, "Port `%s' not valid\n", arg);
 
+	random = strchr(arg, ':');
+	if (random) {
+		if (*(random+1) == 'r') {
+			mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+			*random = '\0';
+		} else {
+			exit_error(PARAMETER_PROBLEM, "Random specification `%s' not valid\n", arg);
+		}
+	}
+
 	dash = strchr(arg, '-');
 	if (!dash) {
 		mr->range[0].min.tcp.port
@@ -125,8 +141,11 @@
 		printf("%hu", ntohs(r->min.tcp.port));
 		if (r->max.tcp.port != r->min.tcp.port)
 			printf("-%hu", ntohs(r->max.tcp.port));
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random");
 		printf(" ");
-	}
+	} else if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		printf("random ");
 }
 
 /* Saves the union ipt_targinfo in parsable form to stdout. */
@@ -141,8 +160,11 @@
 		printf("--to-ports %hu", ntohs(r->min.tcp.port));
 		if (r->max.tcp.port != r->min.tcp.port)
 			printf("-%hu", ntohs(r->max.tcp.port));
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random");
 		printf(" ");
-	}
+	} else if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+		printf("--to-ports random ");
 }
 
 static struct iptables_target masq = { NULL,
Index: extensions/libipt_SNAT.c
===================================================================
--- extensions/libipt_SNAT.c	(révision 6735)
+++ extensions/libipt_SNAT.c	(copie de travail)
@@ -22,9 +22,11 @@
 {
 	printf(
 "SNAT v%s options:\n"
-" --to-source <ipaddr>[-<ipaddr>][:port-port]\n"
+" --to-source <ipaddr>[-<ipaddr>][:port-port][:random]\n"
 "				Address to map source to.\n"
-"				(You can use this more than once)\n\n",
+"				(You can use this more than once)\n"
+"				random adds randomness in port selection\n"
+"				to avoid attack by port prediction\n",
 IPTABLES_VERSION);
 }
 
@@ -57,7 +59,7 @@
 parse_to(char *arg, int portok, struct ipt_natinfo *info)
 {
 	struct ip_nat_range range;
-	char *colon, *dash, *error;
+	char *colon, *dash, *random;
 	struct in_addr *ip;
 
 	memset(&range, 0, sizeof(range));
@@ -66,44 +68,55 @@
 	if (colon) {
 		int port;
 
-		if (!portok)
-			exit_error(PARAMETER_PROBLEM,
-				   "Need TCP or UDP with port specification");
+		if (*(colon+1) == 'r') {
+			/* syntax is IP1-IP2:R we just set random */
+			range.flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		} else {
+			if (!portok)
+				exit_error(PARAMETER_PROBLEM,
+						"Need TCP or UDP with port specification");
 
-		range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+			range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 
-		port = atoi(colon+1);
-		if (port <= 0 || port > 65535)
-			exit_error(PARAMETER_PROBLEM,
-				   "Port `%s' not valid\n", colon+1);
+			port = atoi(colon+1);
+			if (port <= 0 || port > 65535)
+				exit_error(PARAMETER_PROBLEM,
+						"Port `%s' not valid\n", colon+1);
 
-		error = strchr(colon+1, ':');
-		if (error)
-			exit_error(PARAMETER_PROBLEM,
-				   "Invalid port:port syntax - use dash\n");
+			random = strchr(colon+1, ':');
+			if (random) {
+				if (*(random+1) != 'r'){
+				exit_error(PARAMETER_PROBLEM,
+						"Invalid port:port syntax - use dash\n");
+				} else {
+					range.flags |= IP_NAT_RANGE_PROTO_RANDOM;
+					*random = '\0';
+				}
+			}
 
-		dash = strchr(colon, '-');
-		if (!dash) {
-			range.min.tcp.port
-				= range.max.tcp.port
-				= htons(port);
-		} else {
-			int maxport;
+			dash = strchr(colon, '-');
+			if (!dash) {
+				range.min.tcp.port
+					= range.max.tcp.port
+					= htons(port);
+			} else {
+				int maxport;
 
-			maxport = atoi(dash + 1);
-			if (maxport <= 0 || maxport > 65535)
-				exit_error(PARAMETER_PROBLEM,
-					   "Port `%s' not valid\n", dash+1);
-			if (maxport < port)
-				/* People are stupid. */
-				exit_error(PARAMETER_PROBLEM,
-					   "Port range `%s' funky\n", colon+1);
-			range.min.tcp.port = htons(port);
-			range.max.tcp.port = htons(maxport);
+				maxport = atoi(dash + 1);
+				if (maxport <= 0 || maxport > 65535)
+					exit_error(PARAMETER_PROBLEM,
+							"Port `%s' not valid\n", dash+1);
+				if (maxport < port)
+					/* People are stupid. */
+					exit_error(PARAMETER_PROBLEM,
+							"Port range `%s' funky\n", colon+1);
+				range.min.tcp.port = htons(port);
+				range.max.tcp.port = htons(maxport);
+			}
+			/* Starts with a colon? No IP info...*/
+			if (colon == arg)
+				return &(append_range(info, &range)->t);
 		}
-		/* Starts with a colon? No IP info...*/
-		if (colon == arg)
-			return &(append_range(info, &range)->t);
 		*colon = '\0';
 	}
 
@@ -197,6 +210,9 @@
 		if (r->max.tcp.port != r->min.tcp.port)
 			printf("-%hu", ntohs(r->max.tcp.port));
 	}
+	if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		printf(":random");
+	}
 }
 
 /* Prints out the targinfo. */
Index: extensions/libipt_SAME.c
===================================================================
--- extensions/libipt_SAME.c	(révision 6735)
+++ extensions/libipt_SAME.c	(copie de travail)
@@ -16,7 +16,7 @@
 {
 	printf(
 "SAME v%s options:\n"
-" --to <ipaddr>-<ipaddr>\n"
+" --to <ipaddr>-<ipaddr>[:random]\n"
 "				Addresses to map source to.\n"
 "				 May be specified more than\n"
 "				  once for multiple ranges.\n"
@@ -49,10 +49,21 @@
 static void
 parse_to(char *arg, struct ip_nat_range *range)
 {
-	char *dash;
+	char *dash, *random;
 	struct in_addr *ip;
 
 	range->flags |= IP_NAT_RANGE_MAP_IPS;
+
+	random = strchr(arg, ':');
+	if (random) {
+		if (*(random+1) == 'r') {
+			range->flags |= IP_NAT_RANGE_PROTO_RANDOM;
+			*random = '\0';
+		} else {
+			exit_error(PARAMETER_PROBLEM, "Random specification `%s' not valid\n", random+1);
+		}
+	}
+
 	dash = strchr(arg, '-');
 
 	if (dash)
@@ -90,7 +101,7 @@
 	struct ipt_same_info *mr
 		= (struct ipt_same_info *)(*target)->data;
 
-	switch (c) {
+switch (c) {
 	case '1':
 		if (mr->rangesize == IPT_SAME_MAX_RANGE)
 			exit_error(PARAMETER_PROBLEM,
@@ -151,10 +162,13 @@
 		printf("%s", addr_to_dotted(&a));
 		a.s_addr = r->max_ip;
 		
-		if (r->min_ip == r->max_ip)
+		if (r->min_ip != r->max_ip)
+			printf("-%s", addr_to_dotted(&a));
+
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random ");
+		else
 			printf(" ");
-		else
-			printf("-%s ", addr_to_dotted(&a));
 	}
 	
 	if (mr->info & IPT_SAME_NODST)
@@ -177,10 +191,13 @@
 		printf("--to %s", addr_to_dotted(&a));
 		a.s_addr = r->max_ip;
 
-		if (r->min_ip == r->max_ip)
+		if (r->min_ip != r->max_ip)
+			printf("-%s", addr_to_dotted(&a));
+
+		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf(":random ");
+		else
 			printf(" ");
-		else
-			printf("-%s ", addr_to_dotted(&a));
 	}
 	
 	if (mr->info & IPT_SAME_NODST)

[-- Attachment #2: Ceci est une partie de message numériquement signée --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-02-24 14:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-05 13:25 Resend [patch 2/2] iptables: add random option to SNAT Eric Leblond
2007-02-05 15:06 ` Patrick McHardy
2007-02-05 15:55   ` Eric Leblond
2007-02-12 13:40     ` Patrick McHardy
2007-02-12 18:38       ` Jan Engelhardt
2007-02-12 19:38         ` Patrick McHardy
2007-02-24 14:10       ` Eric Leblond
2007-02-24 14:21         ` Patrick McHardy
  -- strict thread matches above, loose matches on Subject: below --
2007-01-12 16:59 [Patch 0/2] Avoid direct connections between NATed hosts Eric Leblond
2007-01-12 22:53 ` Jan Engelhardt
2007-01-13 12:06   ` Resend [Patch 2/2] iptables: add random option to SNAT Eric Leblond

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.