From ae4b0b3aa70c67f2eff303a3e75834e45c3794a7 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sat, 24 Feb 2007 15:11:33 +0000 Subject: iptables: add random option to SNAT (Eric Leblond) --- extensions/libipt_MASQUERADE.c | 23 ++++++++++++++++++++- extensions/libipt_MASQUERADE.man | 10 ++++++++++ extensions/libipt_SAME.c | 43 ++++++++++++++++++++++++++++++++++++++-- extensions/libipt_SAME.man | 4 ++++ extensions/libipt_SNAT.c | 39 ++++++++++++++++++++++++++++++++---- extensions/libipt_SNAT.man | 7 +++++-- 6 files changed, 117 insertions(+), 9 deletions(-) (limited to 'extensions') diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c index 7eddcc09..e06333ab 100644 --- a/extensions/libipt_MASQUERADE.c +++ b/extensions/libipt_MASQUERADE.c @@ -15,12 +15,21 @@ help(void) printf( "MASQUERADE v%s options:\n" " --to-ports [-]\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(int c, char **argv, int invert, unsigned int *flags, 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 @@ print(const struct ipt_ip *ip, 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. */ diff --git a/extensions/libipt_MASQUERADE.man b/extensions/libipt_MASQUERADE.man index e82063cc..01dea51c 100644 --- a/extensions/libipt_MASQUERADE.man +++ b/extensions/libipt_MASQUERADE.man @@ -14,9 +14,19 @@ any established connections are lost anyway). It takes one option: .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). + + diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c index 4eda2237..625a78a7 100644 --- a/extensions/libipt_SAME.c +++ b/extensions/libipt_SAME.c @@ -22,13 +22,22 @@ help(void) " 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 @@ parse_to(char *arg, struct ip_nat_range *range) #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 @@ parse(int c, char **argv, int invert, unsigned int *flags, { 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 @@ parse(int c, char **argv, int invert, unsigned int *flags, "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 @@ parse(int c, char **argv, int invert, unsigned int *flags, 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 @@ print(const struct ipt_ip *ip, 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 @@ print(const struct ipt_ip *ip, 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. */ diff --git a/extensions/libipt_SAME.man b/extensions/libipt_SAME.man index 817c2001..4e88d48d 100644 --- a/extensions/libipt_SAME.man +++ b/extensions/libipt_SAME.man @@ -9,3 +9,7 @@ multiple ranges. .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). diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index 867c9d01..36147397 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -8,6 +8,11 @@ #include #include +#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 @@ help(void) { printf( "SNAT v%s options:\n" -" --to-source [-][:port-port]\n" +" --to-source [-][: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 @@ IPTABLES_VERSION); 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 @@ parse(int c, char **argv, int invert, unsigned int *flags, 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,8 +175,22 @@ parse(int c, char **argv, int invert, unsigned int *flags, "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 @@ parse(int c, char **argv, int invert, unsigned int *flags, /* 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 @@ static void print_range(const struct ip_nat_range *r) 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. */ diff --git a/extensions/libipt_SNAT.man b/extensions/libipt_SNAT.man index 2d9427f1..daef78f1 100644 --- a/extensions/libipt_SNAT.man +++ b/extensions/libipt_SNAT.man @@ -7,7 +7,7 @@ modified (and all future packets in this connection will also be 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 @@ or 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 -- cgit v1.2.3