* [Patch 0/2] Avoid direct connections between NATed hosts
@ 2007-01-12 16:59 Eric Leblond
2007-01-12 17:02 ` [Patch 1/2] " Eric Leblond
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: Eric Leblond @ 2007-01-12 16:59 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 951 bytes --]
Hi,
Some algorithms can be used to established direct connections between
NATed hosts. Skype is one of the programs using this kind of "feature".
Some details can be found here :
http://www.heise-security.co.uk/articles/print/82481
It uses the fact that port is usually sequentially increased and is thus
predictable.
This patches against kernel and iptables add the capability to randomize
the source port used when doing SNAT.
Tests have been done and have show that Skype is no more able to
established a direct connection between NATed hosts.
Randomization of the source port can be activated on a per-rule basis
with the following syntax:
iptables -A POSTROUTING -t nat -o eth0 -j SNAT --to 192.168.1.3:random
or
iptables -A POSTROUTING -t nat -o eth0 -j SNAT --to 192.168.1.3:1234-3456:random
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] 14+ messages in thread* [Patch 1/2] Avoid direct connections between NATed hosts 2007-01-12 16:59 [Patch 0/2] Avoid direct connections between NATed hosts Eric Leblond @ 2007-01-12 17:02 ` Eric Leblond 2007-01-12 17:04 ` [Patch 2/2] iptables: add random option to SNAT Eric Leblond ` (2 subsequent siblings) 3 siblings, 0 replies; 14+ messages in thread From: Eric Leblond @ 2007-01-12 17:02 UTC (permalink / raw) To: netfilter-devel [-- Attachment #1.1: Type: text/plain, Size: 213 bytes --] Hi, Here's the patch against Linux git tree (2.6.20-rc4). It modifies nf_nat and ip_nat. 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: 0002-Add-flags-on-SNAT-rules-to-add-randomness-in-protocol.txt --] [-- Type: text/plain, Size: 7029 bytes --] Signed-off-by: Eric Leblond <eric@inl.fr> --- include/linux/netfilter_ipv4/ip_nat.h | 1 + include/net/netfilter/nf_nat.h | 1 + net/ipv4/netfilter/ip_nat_core.c | 13 +++++++++++-- net/ipv4/netfilter/ip_nat_proto_tcp.c | 6 ++++++ net/ipv4/netfilter/ip_nat_proto_udp.c | 6 ++++++ net/ipv4/netfilter/nf_nat_core.c | 13 +++++++++++-- net/ipv4/netfilter/nf_nat_proto_tcp.c | 5 +++++ net/ipv4/netfilter/nf_nat_proto_udp.c | 3 +++ 8 files changed, 44 insertions(+), 4 deletions(-) diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h index bdf5536..bbca89a 100644 --- a/include/linux/netfilter_ipv4/ip_nat.h +++ b/include/linux/netfilter_ipv4/ip_nat.h @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */ /* NAT sequence number modifications */ struct ip_nat_seq { diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 61c6206..bc57dd7 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* NAT sequence number modifications */ struct nf_nat_seq { diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 9d1a517..fb0a73e 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -246,8 +246,10 @@ get_unique_tuple(struct ip_conntrack_tup if (maniptype == IP_NAT_MANIP_SRC) { if (find_appropriate_src(orig_tuple, tuple, range)) { DEBUGP("get_unique_tuple: Found current src map\n"); - if (!ip_nat_used_tuple(tuple, conntrack)) - return; + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { + if (!ip_nat_used_tuple(tuple, conntrack)) + return; + } } } @@ -261,6 +263,13 @@ get_unique_tuple(struct ip_conntrack_tup proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); + /* Change protocol info to have some randomization */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + proto->unique_tuple(tuple, range, maniptype, conntrack); + ip_nat_proto_put(proto); + return; + } + /* Only bother mapping if it's not already in range and unique */ if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || proto->in_range(tuple, maniptype, &range->min, &range->max)) diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index b586d18..6869ad7 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -18,6 +18,8 @@ #include <linux/netfilter_ipv4/ip_nat_ru #include <linux/netfilter_ipv4/ip_nat_protocol.h> #include <linux/netfilter_ipv4/ip_nat_core.h> +#include <linux/random.h> + static int tcp_in_range(const struct ip_conntrack_tuple *tuple, enum ip_nat_manip_type maniptype, @@ -75,6 +77,10 @@ tcp_unique_tuple(struct ip_conntrack_tup range_size = ntohs(range->max.tcp.port) - min + 1; } + /* Start from random port to avoid prediction */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + get_random_bytes(&port,sizeof(port)); + } for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!ip_nat_used_tuple(tuple, conntrack)) { diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 5ced087..38d0def 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -18,6 +18,8 @@ #include <linux/netfilter_ipv4/ip_nat_co #include <linux/netfilter_ipv4/ip_nat_rule.h> #include <linux/netfilter_ipv4/ip_nat_protocol.h> +#include <linux/random.h> + static int udp_in_range(const struct ip_conntrack_tuple *tuple, enum ip_nat_manip_type maniptype, @@ -74,6 +76,10 @@ udp_unique_tuple(struct ip_conntrack_tup range_size = ntohs(range->max.udp.port) - min + 1; } + /* Start from random port to avoid prediction */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + get_random_bytes(&port,sizeof(port)); + } for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!ip_nat_used_tuple(tuple, conntrack)) diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 86a9227..9f1b4ec 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -254,8 +254,10 @@ get_unique_tuple(struct nf_conntrack_tup if (maniptype == IP_NAT_MANIP_SRC) { if (find_appropriate_src(orig_tuple, tuple, range)) { DEBUGP("get_unique_tuple: Found current src map\n"); - if (!nf_nat_used_tuple(tuple, ct)) - return; + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { + if (!nf_nat_used_tuple(tuple, ct)) + return; + } } } @@ -269,6 +271,13 @@ get_unique_tuple(struct nf_conntrack_tup proto = nf_nat_proto_find_get(orig_tuple->dst.protonum); + /* Change protocol info to have some randomization */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + proto->unique_tuple(tuple, range, maniptype, ct); + nf_nat_proto_put(proto); + return; + } + /* Only bother mapping if it's not already in range and unique */ if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || proto->in_range(tuple, maniptype, &range->min, &range->max)) && diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index 7e26a7e..c348bc9 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c @@ -18,6 +18,8 @@ #include <net/netfilter/nf_nat_rule.h> #include <net/netfilter/nf_nat_protocol.h> #include <net/netfilter/nf_nat_core.h> +#include <linux/random.h> + static int tcp_in_range(const struct nf_conntrack_tuple *tuple, enum nf_nat_manip_type maniptype, @@ -75,6 +77,9 @@ tcp_unique_tuple(struct nf_conntrack_tup range_size = ntohs(range->max.tcp.port) - min + 1; } + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + get_random_bytes(&port,sizeof(port)); + } for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!nf_nat_used_tuple(tuple, ct)) diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index ab0ce4c..9700f05 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c @@ -73,6 +73,9 @@ udp_unique_tuple(struct nf_conntrack_tup range_size = ntohs(range->max.udp.port) - min + 1; } + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + get_random_bytes(&port,sizeof(port)); + } for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!nf_nat_used_tuple(tuple, ct)) -- 1.4.1 [-- Attachment #2: Ceci est une partie de message numériquement signée --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Patch 2/2] iptables: add random option to SNAT 2007-01-12 16:59 [Patch 0/2] Avoid direct connections between NATed hosts Eric Leblond 2007-01-12 17:02 ` [Patch 1/2] " Eric Leblond @ 2007-01-12 17:04 ` Eric Leblond 2007-01-12 17:11 ` [Patch 0/2] Avoid direct connections between NATed hosts Rémi Denis-Courmont 2007-01-12 22:53 ` Jan Engelhardt 3 siblings, 0 replies; 14+ messages in thread From: Eric Leblond @ 2007-01-12 17:04 UTC (permalink / raw) To: netfilter-devel [-- Attachment #1.1: Type: text/plain, Size: 160 bytes --] Hi, Here's the patch against iptables. 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: 3626 bytes --] 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. */ [-- Attachment #2: Ceci est une partie de message numériquement signée --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Patch 0/2] Avoid direct connections between NATed hosts 2007-01-12 16:59 [Patch 0/2] Avoid direct connections between NATed hosts Eric Leblond 2007-01-12 17:02 ` [Patch 1/2] " Eric Leblond 2007-01-12 17:04 ` [Patch 2/2] iptables: add random option to SNAT Eric Leblond @ 2007-01-12 17:11 ` Rémi Denis-Courmont 2007-01-12 17:20 ` Patrick McHardy 2007-01-12 22:53 ` Jan Engelhardt 3 siblings, 1 reply; 14+ messages in thread From: Rémi Denis-Courmont @ 2007-01-12 17:11 UTC (permalink / raw) To: netfilter-devel [-- Attachment #1: Type: text/plain, Size: 1110 bytes --] Le vendredi 12 janvier 2007 18:59, Eric Leblond a écrit : > Some algorithms can be used to established direct connections between > NATed hosts. Skype is one of the programs using this kind of > "feature". NAT are not *security* devices; NATs are meant to *improve* IP usability by allowing as many protocols as possible to operate even though there are not enough public IP addresses. Making it more difficult for P2P apps to operate through is hence completely not only non-sensical, but a plain contradiction. NATs are sufficiently broken and annoying already to handle for software development; please do not make them worst. Also, this patch goes completely against work-in-progress NAT standards. In this particular case, your approach is a completely associal short-term solution. In the long run, it will simply cause people with normal/correct NATs to have to relay even more traffic when they should not have to, because of people like you. And it certainly won't prevent Skype from running on your network either. -- Rémi Denis-Courmont http://www.remlab.net/ [-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Patch 0/2] Avoid direct connections between NATed hosts 2007-01-12 17:11 ` [Patch 0/2] Avoid direct connections between NATed hosts Rémi Denis-Courmont @ 2007-01-12 17:20 ` Patrick McHardy 2007-01-12 17:39 ` Rémi Denis-Courmont 0 siblings, 1 reply; 14+ messages in thread From: Patrick McHardy @ 2007-01-12 17:20 UTC (permalink / raw) To: Rémi Denis-Courmont; +Cc: netfilter-devel Rémi Denis-Courmont wrote: > Le vendredi 12 janvier 2007 18:59, Eric Leblond a écrit : > >>Some algorithms can be used to established direct connections between >>NATed hosts. Skype is one of the programs using this kind of >>"feature". > > > NAT are not *security* devices; NATs are meant to *improve* IP usability > by allowing as many protocols as possible to operate even though there > are not enough public IP addresses. Making it more difficult for P2P > apps to operate through is hence completely not only non-sensical, but > a plain contradiction. > > NATs are sufficiently broken and annoying already to handle for software > development; please do not make them worst. Also, this patch goes > completely against work-in-progress NAT standards. Fully agreed. > In this particular case, your approach is a completely associal > short-term solution. In the long run, it will simply cause people with > normal/correct NATs to have to relay even more traffic when they should > not have to, because of people like you. And it certainly won't prevent > Skype from running on your network either. Port randomization would still be a useful feature, not to wilfully break skype, but to make spoofing attacks harder. Currently we undo randomization done by the operating system/application. Since its optional I don't see real harm in it. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Patch 0/2] Avoid direct connections between NATed hosts 2007-01-12 17:20 ` Patrick McHardy @ 2007-01-12 17:39 ` Rémi Denis-Courmont 2007-01-17 12:13 ` Patrick McHardy 0 siblings, 1 reply; 14+ messages in thread From: Rémi Denis-Courmont @ 2007-01-12 17:39 UTC (permalink / raw) To: Patrick McHardy; +Cc: netfilter-devel [-- Attachment #1: Type: text/plain, Size: 1600 bytes --] Le vendredi 12 janvier 2007 19:20, Patrick McHardy a écrit : > > In this particular case, your approach is a completely associal > > short-term solution. In the long run, it will simply cause people > > with normal/correct NATs to have to relay even more traffic when > > they should not have to, because of people like you. And it > > certainly won't prevent Skype from running on your network either. > > Port randomization would still be a useful feature, not to wilfully > break skype, but to make spoofing attacks harder. Currently we > undo randomization done by the operating system/application. Since > its optional I don't see real harm in it. Right, randomizing port numbers when they are allocated can make it slightly more difficult to spoof DNS. Does the "regular" socket code picks port at random or not though? And is the port allocation logic shared between socket and NAT code (IMHO it should either be shared or at least be equivalent)? It makes little sense to secure host behind the NAT and not secure yourself; that also imples there should be no need for an iptables option to enable/disable it. My concern is with when (and how) Netfilter NAT code allocates a new port number. If the source private-IP/port are identical, the external NATed-IP/port ought be identical too, and certainly not another randomized value. With that, you have the advantage of random source port numbers (better spoof protection), while not breaking any NAT-aware P2P app. Sorry for the misunderstanding. -- Rémi Denis-Courmont http://www.remlab.net/ [-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Patch 0/2] Avoid direct connections between NATed hosts 2007-01-12 17:39 ` Rémi Denis-Courmont @ 2007-01-17 12:13 ` Patrick McHardy 0 siblings, 0 replies; 14+ messages in thread From: Patrick McHardy @ 2007-01-17 12:13 UTC (permalink / raw) To: Rémi Denis-Courmont; +Cc: netfilter-devel Rémi Denis-Courmont wrote: > Le vendredi 12 janvier 2007 19:20, Patrick McHardy a écrit : > >>Port randomization would still be a useful feature, not to wilfully >>break skype, but to make spoofing attacks harder. Currently we >>undo randomization done by the operating system/application. Since >>its optional I don't see real harm in it. > > > Right, randomizing port numbers when they are allocated can make it > slightly more difficult to spoof DNS. Does the "regular" socket code > picks port at random or not though? And is the port allocation logic > shared between socket and NAT code (IMHO it should either be shared or > at least be equivalent)? It makes little sense to secure host behind > the NAT and not secure yourself; that also imples there should be no > need for an iptables option to enable/disable it. Its not shared, local port allocation is quite different from NAT. > My concern is with when (and how) Netfilter NAT code allocates a new > port number. If the source private-IP/port are identical, the external > NATed-IP/port ought be identical too, and certainly not another > randomized value. > > With that, you have the advantage of random source port numbers (better > spoof protection), while not breaking any NAT-aware P2P app. Thats impossible to guarantee, since we're mapping many address to one we might get clashes. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Patch 0/2] Avoid direct connections between NATed hosts 2007-01-12 16:59 [Patch 0/2] Avoid direct connections between NATed hosts Eric Leblond ` (2 preceding siblings ...) 2007-01-12 17:11 ` [Patch 0/2] Avoid direct connections between NATed hosts Rémi Denis-Courmont @ 2007-01-12 22:53 ` Jan Engelhardt 2007-01-13 12:06 ` Resend [Patch 2/2] iptables: add random option to SNAT Eric Leblond 2007-01-13 21:00 ` Resend [Patch 1/2] Avoid direct connections between NATed hosts Eric Leblond 3 siblings, 2 replies; 14+ messages in thread From: Jan Engelhardt @ 2007-01-12 22:53 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel >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. >+ if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { >+ if (!ip_nat_used_tuple(tuple, conntrack)) >+ return; >+ } > } > } > Drop the extra { } - various places. >@@ -18,6 +18,8 @@ #include <linux/netfilter_ipv4/ip_nat_co > #include <linux/netfilter_ipv4/ip_nat_rule.h> > #include <linux/netfilter_ipv4/ip_nat_protocol.h> > >+#include <linux/random.h> >+ > static int > udp_in_range(const struct ip_conntrack_tuple *tuple, > enum ip_nat_manip_type maniptype, >@@ -74,6 +76,10 @@ udp_unique_tuple(struct ip_conntrack_tup > range_size = ntohs(range->max.udp.port) - min + 1; > } > >+ /* Start from random port to avoid prediction */ >+ if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { >+ get_random_bytes(&port,sizeof(port)); >+ } > for (i = 0; i < range_size; i++, port++) { > *portptr = htons(min + port % range_size); > if (!ip_nat_used_tuple(tuple, conntrack)) Do we want get_random_bytes(), or would net_random() suffice? -`J' -- ^ permalink raw reply [flat|nested] 14+ 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 2007-01-13 21:00 ` Resend [Patch 1/2] Avoid direct connections between NATed hosts Eric Leblond 1 sibling, 0 replies; 14+ 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] 14+ messages in thread
* Resend [Patch 1/2] Avoid direct connections between NATed hosts 2007-01-12 22:53 ` Jan Engelhardt 2007-01-13 12:06 ` Resend [Patch 2/2] iptables: add random option to SNAT Eric Leblond @ 2007-01-13 21:00 ` Eric Leblond 2007-01-17 12:23 ` Patrick McHardy 1 sibling, 1 reply; 14+ messages in thread From: Eric Leblond @ 2007-01-13 21:00 UTC (permalink / raw) To: Jan Engelhardt; +Cc: netfilter-devel [-- Attachment #1.1: Type: text/plain, Size: 443 bytes --] Hi, 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. > > Drop the extra { } - various places. Done > Do we want get_random_bytes(), or would net_random() suffice? It seems that net_random() will be hard enough to predict. Thanks for the idea. BR, -- Eric Leblond <eric@inl.fr> INL [-- Attachment #1.2: 0001-Add-randomness-to-port-selection-in-SNAT.txt --] [-- Type: text/plain, Size: 6971 bytes --] Signed-off-by: Eric Leblond <eric@inl.fr> --- include/linux/netfilter_ipv4/ip_nat.h | 1 + include/net/netfilter/nf_nat.h | 1 + net/ipv4/netfilter/ip_nat_core.c | 12 ++++++++++-- net/ipv4/netfilter/ip_nat_proto_tcp.c | 5 +++++ net/ipv4/netfilter/ip_nat_proto_udp.c | 5 +++++ net/ipv4/netfilter/nf_nat_core.c | 12 ++++++++++-- net/ipv4/netfilter/nf_nat_proto_tcp.c | 4 ++++ net/ipv4/netfilter/nf_nat_proto_udp.c | 2 ++ 8 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h index bdf5536..bbca89a 100644 --- a/include/linux/netfilter_ipv4/ip_nat.h +++ b/include/linux/netfilter_ipv4/ip_nat.h @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */ /* NAT sequence number modifications */ struct ip_nat_seq { diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 61c6206..bc57dd7 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* NAT sequence number modifications */ struct nf_nat_seq { diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 9d1a517..5e08c2b 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tup if (maniptype == IP_NAT_MANIP_SRC) { if (find_appropriate_src(orig_tuple, tuple, range)) { DEBUGP("get_unique_tuple: Found current src map\n"); - if (!ip_nat_used_tuple(tuple, conntrack)) - return; + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) + if (!ip_nat_used_tuple(tuple, conntrack)) + return; } } @@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tup proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); + /* Change protocol info to have some randomization */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + proto->unique_tuple(tuple, range, maniptype, conntrack); + ip_nat_proto_put(proto); + return; + } + /* Only bother mapping if it's not already in range and unique */ if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || proto->in_range(tuple, maniptype, &range->min, &range->max)) diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index b586d18..154a4f7 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -18,6 +18,8 @@ #include <linux/netfilter_ipv4/ip_nat_ru #include <linux/netfilter_ipv4/ip_nat_protocol.h> #include <linux/netfilter_ipv4/ip_nat_core.h> +#include <linux/random.h> + static int tcp_in_range(const struct ip_conntrack_tuple *tuple, enum ip_nat_manip_type maniptype, @@ -75,6 +77,9 @@ tcp_unique_tuple(struct ip_conntrack_tup range_size = ntohs(range->max.tcp.port) - min + 1; } + /* Start from random port to avoid prediction */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = (u_int16_t) net_random(); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!ip_nat_used_tuple(tuple, conntrack)) { diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 5ced087..b87ed20 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -18,6 +18,8 @@ #include <linux/netfilter_ipv4/ip_nat_co #include <linux/netfilter_ipv4/ip_nat_rule.h> #include <linux/netfilter_ipv4/ip_nat_protocol.h> +#include <linux/random.h> + static int udp_in_range(const struct ip_conntrack_tuple *tuple, enum ip_nat_manip_type maniptype, @@ -74,6 +76,9 @@ udp_unique_tuple(struct ip_conntrack_tup range_size = ntohs(range->max.udp.port) - min + 1; } + /* Start from random port to avoid prediction */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = (u_int16_t) net_random(); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!ip_nat_used_tuple(tuple, conntrack)) diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 86a9227..998b255 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -254,8 +254,9 @@ get_unique_tuple(struct nf_conntrack_tup if (maniptype == IP_NAT_MANIP_SRC) { if (find_appropriate_src(orig_tuple, tuple, range)) { DEBUGP("get_unique_tuple: Found current src map\n"); - if (!nf_nat_used_tuple(tuple, ct)) - return; + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) + if (!nf_nat_used_tuple(tuple, ct)) + return; } } @@ -269,6 +270,13 @@ get_unique_tuple(struct nf_conntrack_tup proto = nf_nat_proto_find_get(orig_tuple->dst.protonum); + /* Change protocol info to have some randomization */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + proto->unique_tuple(tuple, range, maniptype, ct); + nf_nat_proto_put(proto); + return; + } + /* Only bother mapping if it's not already in range and unique */ if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || proto->in_range(tuple, maniptype, &range->min, &range->max)) && diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index 7e26a7e..ba211ef 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c @@ -18,6 +18,8 @@ #include <net/netfilter/nf_nat_rule.h> #include <net/netfilter/nf_nat_protocol.h> #include <net/netfilter/nf_nat_core.h> +#include <linux/random.h> + static int tcp_in_range(const struct nf_conntrack_tuple *tuple, enum nf_nat_manip_type maniptype, @@ -75,6 +77,8 @@ tcp_unique_tuple(struct nf_conntrack_tup range_size = ntohs(range->max.tcp.port) - min + 1; } + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = (u_int16_t) net_random(); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!nf_nat_used_tuple(tuple, ct)) diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index ab0ce4c..0ce9b83 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c @@ -73,6 +73,8 @@ udp_unique_tuple(struct nf_conntrack_tup range_size = ntohs(range->max.udp.port) - min + 1; } + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = (u_int16_t) net_random(); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!nf_nat_used_tuple(tuple, ct)) -- 1.4.1 [-- Attachment #2: Ceci est une partie de message numériquement signée --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: Resend [Patch 1/2] Avoid direct connections between NATed hosts 2007-01-13 21:00 ` Resend [Patch 1/2] Avoid direct connections between NATed hosts Eric Leblond @ 2007-01-17 12:23 ` Patrick McHardy 2007-01-17 15:18 ` Eric Leblond 0 siblings, 1 reply; 14+ messages in thread From: Patrick McHardy @ 2007-01-17 12:23 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel, Jan Engelhardt Eric Leblond wrote: > diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h > index bdf5536..bbca89a 100644 > --- a/include/linux/netfilter_ipv4/ip_nat.h > +++ b/include/linux/netfilter_ipv4/ip_nat.h > @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! > > #define IP_NAT_RANGE_MAP_IPS 1 > #define IP_NAT_RANGE_PROTO_SPECIFIED 2 > +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */ > > /* NAT sequence number modifications */ > struct ip_nat_seq { > diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h > index 61c6206..bc57dd7 100644 > --- a/include/net/netfilter/nf_nat.h > +++ b/include/net/netfilter/nf_nat.h > @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! > > #define IP_NAT_RANGE_MAP_IPS 1 > #define IP_NAT_RANGE_PROTO_SPECIFIED 2 > +#define IP_NAT_RANGE_PROTO_RANDOM 4 > > /* NAT sequence number modifications */ > struct nf_nat_seq { > diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c > index 9d1a517..5e08c2b 100644 > --- a/net/ipv4/netfilter/ip_nat_core.c > +++ b/net/ipv4/netfilter/ip_nat_core.c > @@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tup > if (maniptype == IP_NAT_MANIP_SRC) { > if (find_appropriate_src(orig_tuple, tuple, range)) { > DEBUGP("get_unique_tuple: Found current src map\n"); > - if (!ip_nat_used_tuple(tuple, conntrack)) > - return; > + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) > + if (!ip_nat_used_tuple(tuple, conntrack)) > + return; > } > } > > @@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tup > > proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); > > + /* Change protocol info to have some randomization */ > + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { This doesn't seem to make much sense for DNAT. Either catch it in the checkentry functions or avoid some other way. > + proto->unique_tuple(tuple, range, maniptype, conntrack); > + ip_nat_proto_put(proto); > + return; > + } > + > /* Only bother mapping if it's not already in range and unique */ > if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) > || proto->in_range(tuple, maniptype, &range->min, &range->max)) > diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c > index b586d18..154a4f7 100644 > --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c > +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c > @@ -18,6 +18,8 @@ #include <linux/netfilter_ipv4/ip_nat_ru > #include <linux/netfilter_ipv4/ip_nat_protocol.h> > #include <linux/netfilter_ipv4/ip_nat_core.h> > > +#include <linux/random.h> Put this next to the other linux/ includes please. > + > static int > tcp_in_range(const struct ip_conntrack_tuple *tuple, > enum ip_nat_manip_type maniptype, > @@ -75,6 +77,9 @@ tcp_unique_tuple(struct ip_conntrack_tup > range_size = ntohs(range->max.tcp.port) - min + 1; > } > > + /* Start from random port to avoid prediction */ > + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) > + port = (u_int16_t) net_random(); No need to cast, also endianness error (port is __be16). > for (i = 0; i < range_size; i++, port++) { > *portptr = htons(min + port % range_size); > if (!ip_nat_used_tuple(tuple, conntrack)) { ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Resend [Patch 1/2] Avoid direct connections between NATed hosts 2007-01-17 12:23 ` Patrick McHardy @ 2007-01-17 15:18 ` Eric Leblond 2007-01-19 15:36 ` Patrick McHardy 2007-01-26 14:00 ` Patrick McHardy 0 siblings, 2 replies; 14+ messages in thread From: Eric Leblond @ 2007-01-17 15:18 UTC (permalink / raw) To: Patrick McHardy; +Cc: netfilter-devel, Jan Engelhardt [-- Attachment #1.1: Type: text/plain, Size: 3733 bytes --] Hi, This patch is a try to apply all the modifications you have asked. BR, Le mercredi 17 janvier 2007 à 13:23 +0100, Patrick McHardy a écrit : > Eric Leblond wrote: > > diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h > > index bdf5536..bbca89a 100644 > > --- a/include/linux/netfilter_ipv4/ip_nat.h > > +++ b/include/linux/netfilter_ipv4/ip_nat.h > > @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! > > > > #define IP_NAT_RANGE_MAP_IPS 1 > > #define IP_NAT_RANGE_PROTO_SPECIFIED 2 > > +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */ > > > > /* NAT sequence number modifications */ > > struct ip_nat_seq { > > diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h > > index 61c6206..bc57dd7 100644 > > --- a/include/net/netfilter/nf_nat.h > > +++ b/include/net/netfilter/nf_nat.h > > @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! > > > > #define IP_NAT_RANGE_MAP_IPS 1 > > #define IP_NAT_RANGE_PROTO_SPECIFIED 2 > > +#define IP_NAT_RANGE_PROTO_RANDOM 4 > > > > /* NAT sequence number modifications */ > > struct nf_nat_seq { > > diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c > > index 9d1a517..5e08c2b 100644 > > --- a/net/ipv4/netfilter/ip_nat_core.c > > +++ b/net/ipv4/netfilter/ip_nat_core.c > > @@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tup > > if (maniptype == IP_NAT_MANIP_SRC) { > > if (find_appropriate_src(orig_tuple, tuple, range)) { > > DEBUGP("get_unique_tuple: Found current src map\n"); > > - if (!ip_nat_used_tuple(tuple, conntrack)) > > - return; > > + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) > > + if (!ip_nat_used_tuple(tuple, conntrack)) > > + return; > > } > > } > > > > @@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tup > > > > proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); > > > > + /* Change protocol info to have some randomization */ > > + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { > > This doesn't seem to make much sense for DNAT. Either catch it in > the checkentry functions or avoid some other way. > > > + proto->unique_tuple(tuple, range, maniptype, conntrack); > > + ip_nat_proto_put(proto); > > + return; > > + } > > + > > /* Only bother mapping if it's not already in range and unique */ > > if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) > > || proto->in_range(tuple, maniptype, &range->min, &range->max)) > > diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c > > index b586d18..154a4f7 100644 > > --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c > > +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c > > @@ -18,6 +18,8 @@ #include <linux/netfilter_ipv4/ip_nat_ru > > #include <linux/netfilter_ipv4/ip_nat_protocol.h> > > #include <linux/netfilter_ipv4/ip_nat_core.h> > > > > +#include <linux/random.h> > > Put this next to the other linux/ includes please. > > > + > > static int > > tcp_in_range(const struct ip_conntrack_tuple *tuple, > > enum ip_nat_manip_type maniptype, > > @@ -75,6 +77,9 @@ tcp_unique_tuple(struct ip_conntrack_tup > > range_size = ntohs(range->max.tcp.port) - min + 1; > > } > > > > + /* Start from random port to avoid prediction */ > > + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) > > + port = (u_int16_t) net_random(); > > No need to cast, also endianness error (port is __be16). > > > for (i = 0; i < range_size; i++, port++) { > > *portptr = htons(min + port % range_size); > > if (!ip_nat_used_tuple(tuple, conntrack)) { [-- Attachment #1.2: 0001-Avoid-direct-connections-between-NATed-hosts.txt --] [-- Type: text/plain, Size: 8219 bytes --] From 3c85074785935c8dfea41915908c196d98e6c47d Mon Sep 17 00:00:00 2001 From: Eric Leblond <eric@inl.fr> Date: Wed, 17 Jan 2007 16:14:23 +0100 Subject: [PATCH] Avoid direct connections between NATed hosts This patch adds the capability to randomize ports choice during NAT. This blocks some software using port prediction to established connections between NATed hosts. Signed-off-by: Eric Leblond <eric@ice-age.(none)> --- include/linux/netfilter_ipv4/ip_nat.h | 1 + include/net/netfilter/nf_nat.h | 1 + net/ipv4/netfilter/ip_nat_core.c | 12 ++++++++++-- net/ipv4/netfilter/ip_nat_proto_tcp.c | 4 ++++ net/ipv4/netfilter/ip_nat_proto_udp.c | 4 ++++ net/ipv4/netfilter/ip_nat_rule.c | 4 ++++ net/ipv4/netfilter/nf_nat_core.c | 12 ++++++++++-- net/ipv4/netfilter/nf_nat_proto_tcp.c | 3 +++ net/ipv4/netfilter/nf_nat_proto_udp.c | 3 +++ net/ipv4/netfilter/nf_nat_rule.c | 4 ++++ 10 files changed, 44 insertions(+), 4 deletions(-) diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h index bdf5536..bbca89a 100644 --- a/include/linux/netfilter_ipv4/ip_nat.h +++ b/include/linux/netfilter_ipv4/ip_nat.h @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */ /* NAT sequence number modifications */ struct ip_nat_seq { diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 61c6206..bc57dd7 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -16,6 +16,7 @@ #define HOOK2MANIP(hooknum) ((hooknum) ! #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 +#define IP_NAT_RANGE_PROTO_RANDOM 4 /* NAT sequence number modifications */ struct nf_nat_seq { diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 9d1a517..5e08c2b 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tup if (maniptype == IP_NAT_MANIP_SRC) { if (find_appropriate_src(orig_tuple, tuple, range)) { DEBUGP("get_unique_tuple: Found current src map\n"); - if (!ip_nat_used_tuple(tuple, conntrack)) - return; + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) + if (!ip_nat_used_tuple(tuple, conntrack)) + return; } } @@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tup proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); + /* Change protocol info to have some randomization */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + proto->unique_tuple(tuple, range, maniptype, conntrack); + ip_nat_proto_put(proto); + return; + } + /* Only bother mapping if it's not already in range and unique */ if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || proto->in_range(tuple, maniptype, &range->min, &range->max)) diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index b586d18..78ff1bb 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -8,6 +8,7 @@ #include <linux/types.h> #include <linux/init.h> +#include <linux/random.h> #include <linux/netfilter.h> #include <linux/ip.h> #include <linux/tcp.h> @@ -75,6 +76,9 @@ tcp_unique_tuple(struct ip_conntrack_tup range_size = ntohs(range->max.tcp.port) - min + 1; } + /* Start from random port to avoid prediction */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = __cpu_to_be16(net_random()); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!ip_nat_used_tuple(tuple, conntrack)) { diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 5ced087..752a292 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -8,6 +8,7 @@ #include <linux/types.h> #include <linux/init.h> +#include <linux/random.h> #include <linux/netfilter.h> #include <linux/ip.h> #include <linux/udp.h> @@ -74,6 +75,9 @@ udp_unique_tuple(struct ip_conntrack_tup range_size = ntohs(range->max.udp.port) - min + 1; } + /* Start from random port to avoid prediction */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = __cpu_to_be16(net_random()); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!ip_nat_used_tuple(tuple, conntrack)) diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index a176aa3..6ebaad3 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c @@ -193,6 +193,10 @@ static int ipt_dnat_checkentry(const cha printk("DNAT: multiple ranges no longer supported\n"); return 0; } + if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) { + printk("DNAT: port randomization not supported\n"); + return 0; + } return 1; } diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 86a9227..998b255 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -254,8 +254,9 @@ get_unique_tuple(struct nf_conntrack_tup if (maniptype == IP_NAT_MANIP_SRC) { if (find_appropriate_src(orig_tuple, tuple, range)) { DEBUGP("get_unique_tuple: Found current src map\n"); - if (!nf_nat_used_tuple(tuple, ct)) - return; + if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) + if (!nf_nat_used_tuple(tuple, ct)) + return; } } @@ -269,6 +270,13 @@ get_unique_tuple(struct nf_conntrack_tup proto = nf_nat_proto_find_get(orig_tuple->dst.protonum); + /* Change protocol info to have some randomization */ + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { + proto->unique_tuple(tuple, range, maniptype, ct); + nf_nat_proto_put(proto); + return; + } + /* Only bother mapping if it's not already in range and unique */ if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || proto->in_range(tuple, maniptype, &range->min, &range->max)) && diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index 7e26a7e..f0e37f0 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c @@ -8,6 +8,7 @@ #include <linux/types.h> #include <linux/init.h> +#include <linux/random.h> #include <linux/ip.h> #include <linux/tcp.h> @@ -75,6 +76,8 @@ tcp_unique_tuple(struct nf_conntrack_tup range_size = ntohs(range->max.tcp.port) - min + 1; } + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = __cpu_to_be16(net_random()); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!nf_nat_used_tuple(tuple, ct)) diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index ab0ce4c..8a46521 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c @@ -8,6 +8,7 @@ #include <linux/types.h> #include <linux/init.h> +#include <linux/random.h> #include <linux/ip.h> #include <linux/udp.h> @@ -73,6 +74,8 @@ udp_unique_tuple(struct nf_conntrack_tup range_size = ntohs(range->max.udp.port) - min + 1; } + if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) + port = __cpu_to_be16(net_random()); for (i = 0; i < range_size; i++, port++) { *portptr = htons(min + port % range_size); if (!nf_nat_used_tuple(tuple, ct)) diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index b868ee0..3745efe 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -226,6 +226,10 @@ static int ipt_dnat_checkentry(const cha printk("DNAT: multiple ranges no longer supported\n"); return 0; } + if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) { + printk("DNAT: port randomization not supported\n"); + return 0; + } return 1; } -- 1.4.1 [-- Attachment #2: Ceci est une partie de message numériquement signée --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: Resend [Patch 1/2] Avoid direct connections between NATed hosts 2007-01-17 15:18 ` Eric Leblond @ 2007-01-19 15:36 ` Patrick McHardy 2007-01-26 14:00 ` Patrick McHardy 1 sibling, 0 replies; 14+ messages in thread From: Patrick McHardy @ 2007-01-19 15:36 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel, Jan Engelhardt Eric Leblond wrote: >>> >>>+ /* Start from random port to avoid prediction */ >>>+ if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) >>>+ port = (u_int16_t) net_random(); >> >>No need to cast, also endianness error (port is __be16). >>>diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c >>>index b586d18..78ff1bb 100644 >>>--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c >>>+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c >>>@@ -8,6 +8,7 @@ >>> >>> #include <linux/types.h> >>> #include <linux/init.h> >>>+#include <linux/random.h> >>> #include <linux/netfilter.h> >>> #include <linux/ip.h> >>> #include <linux/tcp.h> >>>@@ -75,6 +76,9 @@ tcp_unique_tuple(struct ip_conntrack_tup >>> range_size = ntohs(range->max.tcp.port) - min + 1; >>> } >>> >>>+ /* Start from random port to avoid prediction */ >>>+ if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) >>>+ port = __cpu_to_be16(net_random()); Sorry that was my mistake, port is host endian, I can fix that before applying. Other than that it looks fine, if there are no objections from other people I'm going to apply it this weekend. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Resend [Patch 1/2] Avoid direct connections between NATed hosts 2007-01-17 15:18 ` Eric Leblond 2007-01-19 15:36 ` Patrick McHardy @ 2007-01-26 14:00 ` Patrick McHardy 1 sibling, 0 replies; 14+ messages in thread From: Patrick McHardy @ 2007-01-26 14:00 UTC (permalink / raw) To: Eric Leblond; +Cc: netfilter-devel, Jan Engelhardt Eric Leblond wrote: > This patch is a try to apply all the modifications you have asked. Queued for 2.6.21, thanks Eric. ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2007-01-26 14:00 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-01-12 16:59 [Patch 0/2] Avoid direct connections between NATed hosts Eric Leblond 2007-01-12 17:02 ` [Patch 1/2] " Eric Leblond 2007-01-12 17:04 ` [Patch 2/2] iptables: add random option to SNAT Eric Leblond 2007-01-12 17:11 ` [Patch 0/2] Avoid direct connections between NATed hosts Rémi Denis-Courmont 2007-01-12 17:20 ` Patrick McHardy 2007-01-12 17:39 ` Rémi Denis-Courmont 2007-01-17 12:13 ` Patrick McHardy 2007-01-12 22:53 ` Jan Engelhardt 2007-01-13 12:06 ` Resend [Patch 2/2] iptables: add random option to SNAT Eric Leblond 2007-01-13 21:00 ` Resend [Patch 1/2] Avoid direct connections between NATed hosts Eric Leblond 2007-01-17 12:23 ` Patrick McHardy 2007-01-17 15:18 ` Eric Leblond 2007-01-19 15:36 ` Patrick McHardy 2007-01-26 14:00 ` Patrick McHardy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).