[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>
This commit is contained in:
committed by
David S. Miller
parent
cdd289a2f8
commit
41f4689a7c
@@ -16,6 +16,7 @@ enum ip_nat_manip_type
|
|||||||
|
|
||||||
#define IP_NAT_RANGE_MAP_IPS 1
|
#define IP_NAT_RANGE_MAP_IPS 1
|
||||||
#define IP_NAT_RANGE_PROTO_SPECIFIED 2
|
#define IP_NAT_RANGE_PROTO_SPECIFIED 2
|
||||||
|
#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */
|
||||||
|
|
||||||
/* NAT sequence number modifications */
|
/* NAT sequence number modifications */
|
||||||
struct ip_nat_seq {
|
struct ip_nat_seq {
|
||||||
|
@@ -16,6 +16,7 @@ enum nf_nat_manip_type
|
|||||||
|
|
||||||
#define IP_NAT_RANGE_MAP_IPS 1
|
#define IP_NAT_RANGE_MAP_IPS 1
|
||||||
#define IP_NAT_RANGE_PROTO_SPECIFIED 2
|
#define IP_NAT_RANGE_PROTO_SPECIFIED 2
|
||||||
|
#define IP_NAT_RANGE_PROTO_RANDOM 4
|
||||||
|
|
||||||
/* NAT sequence number modifications */
|
/* NAT sequence number modifications */
|
||||||
struct nf_nat_seq {
|
struct nf_nat_seq {
|
||||||
|
@@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
|
|||||||
if (maniptype == IP_NAT_MANIP_SRC) {
|
if (maniptype == IP_NAT_MANIP_SRC) {
|
||||||
if (find_appropriate_src(orig_tuple, tuple, range)) {
|
if (find_appropriate_src(orig_tuple, tuple, range)) {
|
||||||
DEBUGP("get_unique_tuple: Found current src map\n");
|
DEBUGP("get_unique_tuple: Found current src map\n");
|
||||||
if (!ip_nat_used_tuple(tuple, conntrack))
|
if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
|
||||||
return;
|
if (!ip_nat_used_tuple(tuple, conntrack))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
|
|||||||
|
|
||||||
proto = ip_nat_proto_find_get(orig_tuple->dst.protonum);
|
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 */
|
/* Only bother mapping if it's not already in range and unique */
|
||||||
if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
|
if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
|
||||||
|| proto->in_range(tuple, maniptype, &range->min, &range->max))
|
|| proto->in_range(tuple, maniptype, &range->min, &range->max))
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/random.h>
|
||||||
#include <linux/netfilter.h>
|
#include <linux/netfilter.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
@@ -75,6 +76,10 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple,
|
|||||||
range_size = ntohs(range->max.tcp.port) - min + 1;
|
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 = net_random();
|
||||||
|
|
||||||
for (i = 0; i < range_size; i++, port++) {
|
for (i = 0; i < range_size; i++, port++) {
|
||||||
*portptr = htons(min + port % range_size);
|
*portptr = htons(min + port % range_size);
|
||||||
if (!ip_nat_used_tuple(tuple, conntrack)) {
|
if (!ip_nat_used_tuple(tuple, conntrack)) {
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/random.h>
|
||||||
#include <linux/netfilter.h>
|
#include <linux/netfilter.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
@@ -74,6 +75,10 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
|
|||||||
range_size = ntohs(range->max.udp.port) - min + 1;
|
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 = net_random();
|
||||||
|
|
||||||
for (i = 0; i < range_size; i++, port++) {
|
for (i = 0; i < range_size; i++, port++) {
|
||||||
*portptr = htons(min + port % range_size);
|
*portptr = htons(min + port % range_size);
|
||||||
if (!ip_nat_used_tuple(tuple, conntrack))
|
if (!ip_nat_used_tuple(tuple, conntrack))
|
||||||
|
@@ -193,6 +193,10 @@ static int ipt_dnat_checkentry(const char *tablename,
|
|||||||
printk("DNAT: multiple ranges no longer supported\n");
|
printk("DNAT: multiple ranges no longer supported\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
|
||||||
|
printk("DNAT: port randomization not supported\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -254,8 +254,9 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
if (maniptype == IP_NAT_MANIP_SRC) {
|
if (maniptype == IP_NAT_MANIP_SRC) {
|
||||||
if (find_appropriate_src(orig_tuple, tuple, range)) {
|
if (find_appropriate_src(orig_tuple, tuple, range)) {
|
||||||
DEBUGP("get_unique_tuple: Found current src map\n");
|
DEBUGP("get_unique_tuple: Found current src map\n");
|
||||||
if (!nf_nat_used_tuple(tuple, ct))
|
if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
|
||||||
return;
|
if (!nf_nat_used_tuple(tuple, ct))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,6 +270,13 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
|
|
||||||
proto = nf_nat_proto_find_get(orig_tuple->dst.protonum);
|
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 */
|
/* Only bother mapping if it's not already in range and unique */
|
||||||
if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
|
if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
|
||||||
proto->in_range(tuple, maniptype, &range->min, &range->max)) &&
|
proto->in_range(tuple, maniptype, &range->min, &range->max)) &&
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/random.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
|
|
||||||
@@ -75,6 +76,9 @@ tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
range_size = ntohs(range->max.tcp.port) - min + 1;
|
range_size = ntohs(range->max.tcp.port) - min + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
|
||||||
|
port = net_random();
|
||||||
|
|
||||||
for (i = 0; i < range_size; i++, port++) {
|
for (i = 0; i < range_size; i++, port++) {
|
||||||
*portptr = htons(min + port % range_size);
|
*portptr = htons(min + port % range_size);
|
||||||
if (!nf_nat_used_tuple(tuple, ct))
|
if (!nf_nat_used_tuple(tuple, ct))
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/random.h>
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
|
|
||||||
@@ -73,6 +74,9 @@ udp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
|||||||
range_size = ntohs(range->max.udp.port) - min + 1;
|
range_size = ntohs(range->max.udp.port) - min + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
|
||||||
|
port = net_random();
|
||||||
|
|
||||||
for (i = 0; i < range_size; i++, port++) {
|
for (i = 0; i < range_size; i++, port++) {
|
||||||
*portptr = htons(min + port % range_size);
|
*portptr = htons(min + port % range_size);
|
||||||
if (!nf_nat_used_tuple(tuple, ct))
|
if (!nf_nat_used_tuple(tuple, ct))
|
||||||
|
@@ -226,6 +226,10 @@ static int ipt_dnat_checkentry(const char *tablename,
|
|||||||
printk("DNAT: multiple ranges no longer supported\n");
|
printk("DNAT: multiple ranges no longer supported\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
|
||||||
|
printk("DNAT: port randomization not supported\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user