diff options
author | Eric Leblond <eric@inl.fr> | 2007-02-07 18:10:09 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-02-08 15:39:17 -0500 |
commit | 41f4689a7c8cd76b77864461b3c58fde8f322b2c (patch) | |
tree | 29be7597bc02158ca41261f365ebcbd8047dd56f /net | |
parent | cdd289a2f833b93e65b9a09a02c37f47a58140a8 (diff) |
[NETFILTER]: NAT: optional source port randomization support
This patch adds support to NAT to randomize source ports.
Signed-off-by: Eric Leblond <eric@inl.fr>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/ip_nat_core.c | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_tcp.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_udp.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_rule.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_proto_tcp.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_proto_udp.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_rule.c | 4 |
8 files changed, 46 insertions, 4 deletions
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 9d1a5175dcd4..5e08c2bf887d 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_tuple *tuple, | |||
246 | if (maniptype == IP_NAT_MANIP_SRC) { | 246 | if (maniptype == IP_NAT_MANIP_SRC) { |
247 | if (find_appropriate_src(orig_tuple, tuple, range)) { | 247 | if (find_appropriate_src(orig_tuple, tuple, range)) { |
248 | DEBUGP("get_unique_tuple: Found current src map\n"); | 248 | DEBUGP("get_unique_tuple: Found current src map\n"); |
249 | if (!ip_nat_used_tuple(tuple, conntrack)) | 249 | if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) |
250 | return; | 250 | if (!ip_nat_used_tuple(tuple, conntrack)) |
251 | return; | ||
251 | } | 252 | } |
252 | } | 253 | } |
253 | 254 | ||
@@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, | |||
261 | 262 | ||
262 | proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); | 263 | proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); |
263 | 264 | ||
265 | /* Change protocol info to have some randomization */ | ||
266 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { | ||
267 | proto->unique_tuple(tuple, range, maniptype, conntrack); | ||
268 | ip_nat_proto_put(proto); | ||
269 | return; | ||
270 | } | ||
271 | |||
264 | /* Only bother mapping if it's not already in range and unique */ | 272 | /* Only bother mapping if it's not already in range and unique */ |
265 | if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) | 273 | if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) |
266 | || proto->in_range(tuple, maniptype, &range->min, &range->max)) | 274 | || 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 b586d18b3fb3..14ff24f53a7a 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/random.h> | ||
11 | #include <linux/netfilter.h> | 12 | #include <linux/netfilter.h> |
12 | #include <linux/ip.h> | 13 | #include <linux/ip.h> |
13 | #include <linux/tcp.h> | 14 | #include <linux/tcp.h> |
@@ -75,6 +76,10 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple, | |||
75 | range_size = ntohs(range->max.tcp.port) - min + 1; | 76 | range_size = ntohs(range->max.tcp.port) - min + 1; |
76 | } | 77 | } |
77 | 78 | ||
79 | /* Start from random port to avoid prediction */ | ||
80 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) | ||
81 | port = net_random(); | ||
82 | |||
78 | for (i = 0; i < range_size; i++, port++) { | 83 | for (i = 0; i < range_size; i++, port++) { |
79 | *portptr = htons(min + port % range_size); | 84 | *portptr = htons(min + port % range_size); |
80 | if (!ip_nat_used_tuple(tuple, conntrack)) { | 85 | 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 5ced0877b32f..dfd521672891 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/random.h> | ||
11 | #include <linux/netfilter.h> | 12 | #include <linux/netfilter.h> |
12 | #include <linux/ip.h> | 13 | #include <linux/ip.h> |
13 | #include <linux/udp.h> | 14 | #include <linux/udp.h> |
@@ -74,6 +75,10 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple, | |||
74 | range_size = ntohs(range->max.udp.port) - min + 1; | 75 | range_size = ntohs(range->max.udp.port) - min + 1; |
75 | } | 76 | } |
76 | 77 | ||
78 | /* Start from random port to avoid prediction */ | ||
79 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) | ||
80 | port = net_random(); | ||
81 | |||
77 | for (i = 0; i < range_size; i++, port++) { | 82 | for (i = 0; i < range_size; i++, port++) { |
78 | *portptr = htons(min + port % range_size); | 83 | *portptr = htons(min + port % range_size); |
79 | if (!ip_nat_used_tuple(tuple, conntrack)) | 84 | 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 a176aa3031e0..6ebaad36c06d 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 char *tablename, | |||
193 | printk("DNAT: multiple ranges no longer supported\n"); | 193 | printk("DNAT: multiple ranges no longer supported\n"); |
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) { | ||
197 | printk("DNAT: port randomization not supported\n"); | ||
198 | return 0; | ||
199 | } | ||
196 | return 1; | 200 | return 1; |
197 | } | 201 | } |
198 | 202 | ||
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 86a92272b053..998b2557692c 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_tuple *tuple, | |||
254 | if (maniptype == IP_NAT_MANIP_SRC) { | 254 | if (maniptype == IP_NAT_MANIP_SRC) { |
255 | if (find_appropriate_src(orig_tuple, tuple, range)) { | 255 | if (find_appropriate_src(orig_tuple, tuple, range)) { |
256 | DEBUGP("get_unique_tuple: Found current src map\n"); | 256 | DEBUGP("get_unique_tuple: Found current src map\n"); |
257 | if (!nf_nat_used_tuple(tuple, ct)) | 257 | if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) |
258 | return; | 258 | if (!nf_nat_used_tuple(tuple, ct)) |
259 | return; | ||
259 | } | 260 | } |
260 | } | 261 | } |
261 | 262 | ||
@@ -269,6 +270,13 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
269 | 270 | ||
270 | proto = nf_nat_proto_find_get(orig_tuple->dst.protonum); | 271 | proto = nf_nat_proto_find_get(orig_tuple->dst.protonum); |
271 | 272 | ||
273 | /* Change protocol info to have some randomization */ | ||
274 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) { | ||
275 | proto->unique_tuple(tuple, range, maniptype, ct); | ||
276 | nf_nat_proto_put(proto); | ||
277 | return; | ||
278 | } | ||
279 | |||
272 | /* Only bother mapping if it's not already in range and unique */ | 280 | /* Only bother mapping if it's not already in range and unique */ |
273 | if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || | 281 | if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || |
274 | proto->in_range(tuple, maniptype, &range->min, &range->max)) && | 282 | 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 7e26a7e9bee1..439164c7a626 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/random.h> | ||
11 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
12 | #include <linux/tcp.h> | 13 | #include <linux/tcp.h> |
13 | 14 | ||
@@ -75,6 +76,9 @@ tcp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
75 | range_size = ntohs(range->max.tcp.port) - min + 1; | 76 | range_size = ntohs(range->max.tcp.port) - min + 1; |
76 | } | 77 | } |
77 | 78 | ||
79 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) | ||
80 | port = net_random(); | ||
81 | |||
78 | for (i = 0; i < range_size; i++, port++) { | 82 | for (i = 0; i < range_size; i++, port++) { |
79 | *portptr = htons(min + port % range_size); | 83 | *portptr = htons(min + port % range_size); |
80 | if (!nf_nat_used_tuple(tuple, ct)) | 84 | 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 ab0ce4c8699f..8cae6e063bb6 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/random.h> | ||
11 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
12 | #include <linux/udp.h> | 13 | #include <linux/udp.h> |
13 | 14 | ||
@@ -73,6 +74,9 @@ udp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
73 | range_size = ntohs(range->max.udp.port) - min + 1; | 74 | range_size = ntohs(range->max.udp.port) - min + 1; |
74 | } | 75 | } |
75 | 76 | ||
77 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) | ||
78 | port = net_random(); | ||
79 | |||
76 | for (i = 0; i < range_size; i++, port++) { | 80 | for (i = 0; i < range_size; i++, port++) { |
77 | *portptr = htons(min + port % range_size); | 81 | *portptr = htons(min + port % range_size); |
78 | if (!nf_nat_used_tuple(tuple, ct)) | 82 | 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 b868ee0195d4..3745efe70302 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 char *tablename, | |||
226 | printk("DNAT: multiple ranges no longer supported\n"); | 226 | printk("DNAT: multiple ranges no longer supported\n"); |
227 | return 0; | 227 | return 0; |
228 | } | 228 | } |
229 | if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) { | ||
230 | printk("DNAT: port randomization not supported\n"); | ||
231 | return 0; | ||
232 | } | ||
229 | return 1; | 233 | return 1; |
230 | } | 234 | } |
231 | 235 | ||