From 0bb8765cc28cf1ddde70f3f5bfed96a067b1ead3 Mon Sep 17 00:00:00 2001 From: "fan.du" Date: Wed, 18 Dec 2013 11:27:22 +0800 Subject: iptables: Add IPv4/6 IPcomp match support This patch enables user to set iptables ACTIONs for IPcomp flow specified by its SPI value. For example: iptables -A OUTPUT -p 108 -m ipcomp --ipcompspi 0x12 -j DROP ip6tables -A OUTPUT -p 108 -m ipcomp --ipcompspi 0x12 -j DROP IPcomp packet with spi as 0x12 will be dropped. Signed-off-by: Fan Du Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_ipcomp.c | 116 ++++++++++++++++++++++++++++++++++++ extensions/libxt_ipcomp.c.man | 7 +++ include/linux/netfilter/xt_ipcomp.h | 16 +++++ 3 files changed, 139 insertions(+) create mode 100644 extensions/libxt_ipcomp.c create mode 100644 extensions/libxt_ipcomp.c.man create mode 100644 include/linux/netfilter/xt_ipcomp.h diff --git a/extensions/libxt_ipcomp.c b/extensions/libxt_ipcomp.c new file mode 100644 index 00000000..b157e7b1 --- /dev/null +++ b/extensions/libxt_ipcomp.c @@ -0,0 +1,116 @@ +#include +#include +#include + +enum { + O_compSPI = 0, + O_compRES, +}; + +static void comp_help(void) +{ + printf( +"comp match options:\n" +"[!] --ipcompspi spi[:spi]\n" +" match spi (range)\n"); +} + +static const struct xt_option_entry comp_opts[] = { + {.name = "ipcompspi", .id = O_compSPI, .type = XTTYPE_UINT32RC, + .flags = XTOPT_INVERT | XTOPT_PUT, + XTOPT_POINTER(struct xt_ipcomp, spis)}, + {.name = "compres", .id = O_compRES, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; +#undef s + +static void comp_parse(struct xt_option_call *cb) +{ + struct xt_ipcomp *compinfo = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_compSPI: + if (cb->nvals == 1) + compinfo->spis[1] = compinfo->spis[0]; + if (cb->invert) + compinfo->invflags |= XT_IPCOMP_INV_SPI; + break; + case O_compRES: + compinfo->hdrres = 1; + break; + } +} + +static void +print_spis(const char *name, uint32_t min, uint32_t max, + int invert) +{ + const char *inv = invert ? "!" : ""; + + if (min != 0 || max != 0xFFFFFFFF || invert) { + if (min == max) + printf("%s:%s%u", name, inv, min); + else + printf("%ss:%s%u:%u", name, inv, min, max); + } +} + +static void comp_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct xt_ipcomp *comp = (struct xt_ipcomp *)match->data; + + printf(" comp "); + print_spis("spi", comp->spis[0], comp->spis[1], + comp->invflags & XT_IPCOMP_INV_SPI); + + if (comp->hdrres) + printf(" reserved"); + + if (comp->invflags & ~XT_IPCOMP_INV_MASK) + printf(" Unknown invflags: 0x%X", + comp->invflags & ~XT_IPCOMP_INV_MASK); +} + +static void comp_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_ipcomp *compinfo = (struct xt_ipcomp *)match->data; + + if (!(compinfo->spis[0] == 0 + && compinfo->spis[1] == 0xFFFFFFFF)) { + printf("%s --ipcompspi ", + (compinfo->invflags & XT_IPCOMP_INV_SPI) ? " !" : ""); + if (compinfo->spis[0] + != compinfo->spis[1]) + printf("%u:%u", + compinfo->spis[0], + compinfo->spis[1]); + else + printf("%u", + compinfo->spis[0]); + } + + if (compinfo->hdrres != 0 ) + printf(" --compres"); +} + +static struct xtables_match comp_mt_reg = { + .name = "ipcomp", + .version = XTABLES_VERSION, + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_ipcomp)), + .userspacesize = XT_ALIGN(sizeof(struct xt_ipcomp)), + .help = comp_help, + .print = comp_print, + .save = comp_save, + .x6_parse = comp_parse, + .x6_options = comp_opts, +}; + +void +_init(void) +{ + xtables_register_match(&comp_mt_reg); +}; + diff --git a/extensions/libxt_ipcomp.c.man b/extensions/libxt_ipcomp.c.man new file mode 100644 index 00000000..f3b17d21 --- /dev/null +++ b/extensions/libxt_ipcomp.c.man @@ -0,0 +1,7 @@ +This module matches the parameters in IPcomp header of IPsec packets. +.TP +[\fB!\fP] \fB\-\-ipcompspi\fP \fIspi\fP[\fB:\fP\fIspi\fP] +Matches IPcomp header CPI value. +.TP +\fB\-\-compres\fP +Matches if the reserved field is filled with zero. diff --git a/include/linux/netfilter/xt_ipcomp.h b/include/linux/netfilter/xt_ipcomp.h new file mode 100644 index 00000000..45c7e40e --- /dev/null +++ b/include/linux/netfilter/xt_ipcomp.h @@ -0,0 +1,16 @@ +#ifndef _XT_IPCOMP_H +#define _XT_IPCOMP_H + +#include + +struct xt_ipcomp { + __u32 spis[2]; /* Security Parameter Index */ + __u8 invflags; /* Inverse flags */ + __u8 hdrres; /* Test of the Reserved Filed */ +}; + +/* Values for "invflags" field in struct xt_ipcomp. */ +#define XT_IPCOMP_INV_SPI 0x01 /* Invert the sense of spi. */ +#define XT_IPCOMP_INV_MASK 0x01 /* All possible flags. */ + +#endif /*_XT_IPCOMP_H*/ -- cgit v1.2.3 From 3cefc136d13f426fd68808ddfd39ada0c90f23db Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sun, 22 Dec 2013 04:15:38 +0100 Subject: iptables: snat: add randomize-full support This patch provides the userspace part for snat in order to make randomize-full support available in {ip,nf}tables. It allows for enabling full port randomization that was motivated in [1] and introduced to the kernel in [2]. Joint work between Hannes Frederic Sowa and Daniel Borkmann. [1] https://sites.google.com/site/hayashulman/files/NIC-derandomisation.pdf [2] http://patchwork.ozlabs.org/patch/304306/ Signed-off-by: Hannes Frederic Sowa Signed-off-by: Daniel Borkmann Signed-off-by: Pablo Neira Ayuso --- extensions/libip6t_SNAT.c | 18 ++++++++++++++---- extensions/libipt_SNAT.c | 18 ++++++++++++++---- extensions/libxt_SNAT.man | 7 ++++++- include/linux/netfilter/nf_nat.h | 12 ++++++++---- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c index 7382ad06..8eb50b8d 100644 --- a/extensions/libip6t_SNAT.c +++ b/extensions/libip6t_SNAT.c @@ -18,11 +18,13 @@ enum { O_TO_SRC = 0, O_RANDOM, + O_RANDOM_FULLY, O_PERSISTENT, O_X_TO_SRC, - F_TO_SRC = 1 << O_TO_SRC, - F_RANDOM = 1 << O_RANDOM, - F_X_TO_SRC = 1 << O_X_TO_SRC, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, + F_RANDOM_FULLY = 1 << O_RANDOM_FULLY, + F_X_TO_SRC = 1 << O_X_TO_SRC, }; static void SNAT_help(void) @@ -31,13 +33,14 @@ static void SNAT_help(void) "SNAT target options:\n" " --to-source [[-]][:port[-port]]\n" " Address to map source to.\n" -"[--random] [--persistent]\n"); +"[--random] [--random-fully] [--persistent]\n"); } static const struct xt_option_entry SNAT_opts[] = { {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, .flags = XTOPT_MAND | XTOPT_MULTI}, {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE}, {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, XTOPT_TABLEEND, }; @@ -180,10 +183,13 @@ static void SNAT_parse(struct xt_option_call *cb) static void SNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_SRC | F_RANDOM; + static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY; struct nf_nat_range *range = cb->data; if ((cb->xflags & f) == f) range->flags |= NF_NAT_RANGE_PROTO_RANDOM; + if ((cb->xflags & r) == r) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY; } static void print_range(const struct nf_nat_range *range) @@ -215,6 +221,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, print_range(range); if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" random-fully"); if (range->flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } @@ -227,6 +235,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) print_range(range); if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); + if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" --random-fully"); if (range->flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c index 1a24f3d8..78d2c2b1 100644 --- a/extensions/libipt_SNAT.c +++ b/extensions/libipt_SNAT.c @@ -11,11 +11,13 @@ enum { O_TO_SRC = 0, O_RANDOM, + O_RANDOM_FULLY, O_PERSISTENT, O_X_TO_SRC, - F_TO_SRC = 1 << O_TO_SRC, - F_RANDOM = 1 << O_RANDOM, - F_X_TO_SRC = 1 << O_X_TO_SRC, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, + F_RANDOM_FULLY = 1 << O_RANDOM_FULLY, + F_X_TO_SRC = 1 << O_X_TO_SRC, }; /* Source NAT data consists of a multi-range, indicating where to map @@ -32,13 +34,14 @@ static void SNAT_help(void) "SNAT target options:\n" " --to-source [[-]][:port[-port]]\n" " Address to map source to.\n" -"[--random] [--persistent]\n"); +"[--random] [--random-fully] [--persistent]\n"); } static const struct xt_option_entry SNAT_opts[] = { {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, .flags = XTOPT_MAND | XTOPT_MULTI}, {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE}, {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, XTOPT_TABLEEND, }; @@ -185,10 +188,13 @@ static void SNAT_parse(struct xt_option_call *cb) static void SNAT_fcheck(struct xt_fcheck_call *cb) { static const unsigned int f = F_TO_SRC | F_RANDOM; + static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY; struct nf_nat_ipv4_multi_range_compat *mr = cb->data; if ((cb->xflags & f) == f) mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; + if ((cb->xflags & r) == r) + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY; } static void print_range(const struct nf_nat_ipv4_range *r) @@ -222,6 +228,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, print_range(&info->mr.range[i]); if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" random"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" random-fully"); if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" persistent"); } @@ -237,6 +245,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) print_range(&info->mr.range[i]); if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM) printf(" --random"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" --random-fully"); if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) printf(" --persistent"); } diff --git a/extensions/libxt_SNAT.man b/extensions/libxt_SNAT.man index f0620a21..8cd0b80e 100644 --- a/extensions/libxt_SNAT.man +++ b/extensions/libxt_SNAT.man @@ -29,7 +29,12 @@ anymore. \fB\-\-random\fP If option \fB\-\-random\fP -is used then port mapping will be randomized (kernel >= 2.6.21). +is used then port mapping will be randomized through a hash-based algorithm (kernel >= 2.6.21). +.TP +\fB\-\-random-fully\fP +If option +\fB\-\-random-fully\fP +is used then port mapping will be fully randomized through a PRNG (kernel >= 3.14). .TP \fB\-\-persistent\fP Gives a client the same source-/destination-address for each connection. diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h index bf0cc373..1ad36591 100644 --- a/include/linux/netfilter/nf_nat.h +++ b/include/linux/netfilter/nf_nat.h @@ -4,10 +4,14 @@ #include #include -#define NF_NAT_RANGE_MAP_IPS 1 -#define NF_NAT_RANGE_PROTO_SPECIFIED 2 -#define NF_NAT_RANGE_PROTO_RANDOM 4 -#define NF_NAT_RANGE_PERSISTENT 8 +#define NF_NAT_RANGE_MAP_IPS (1 << 0) +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) +#define NF_NAT_RANGE_PERSISTENT (1 << 3) +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) + +#define NF_NAT_RANGE_PROTO_RANDOM_ALL \ + (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY) struct nf_nat_ipv4_range { unsigned int flags; -- cgit v1.2.3 From 6465867eb48506687872b838b1ddfee61d1a0aeb Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 23 Dec 2013 18:46:29 +0100 Subject: iptables: add libxt_cgroup frontend This patch adds the user space extension/frontend for process matching based on cgroups from the kernel patch entitled "netfilter: xtables: lightweight process control group matching". Signed-off-by: Daniel Borkmann Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_cgroup.c | 67 +++++++++++++++++++++++++++++++++++++ extensions/libxt_cgroup.man | 15 +++++++++ include/linux/netfilter/xt_cgroup.h | 11 ++++++ 3 files changed, 93 insertions(+) create mode 100644 extensions/libxt_cgroup.c create mode 100644 extensions/libxt_cgroup.man create mode 100644 include/linux/netfilter/xt_cgroup.h diff --git a/extensions/libxt_cgroup.c b/extensions/libxt_cgroup.c new file mode 100644 index 00000000..e304e33c --- /dev/null +++ b/extensions/libxt_cgroup.c @@ -0,0 +1,67 @@ +#include +#include +#include + +enum { + O_CGROUP = 0, +}; + +static void cgroup_help(void) +{ + printf( +"cgroup match options:\n" +"[!] --cgroup fwid Match cgroup fwid\n"); +} + +static const struct xt_option_entry cgroup_opts[] = { + { + .name = "cgroup", + .id = O_CGROUP, + .type = XTTYPE_UINT32, + .flags = XTOPT_INVERT | XTOPT_MAND | XTOPT_PUT, + XTOPT_POINTER(struct xt_cgroup_info, id) + }, + XTOPT_TABLEEND, +}; + +static void cgroup_parse(struct xt_option_call *cb) +{ + struct xt_cgroup_info *cgroupinfo = cb->data; + + xtables_option_parse(cb); + if (cb->invert) + cgroupinfo->invert = true; +} + +static void +cgroup_print(const void *ip, const struct xt_entry_match *match, int numeric) +{ + const struct xt_cgroup_info *info = (void *) match->data; + + printf(" cgroup %s%u", info->invert ? "! ":"", info->id); +} + +static void cgroup_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_cgroup_info *info = (void *) match->data; + + printf("%s --cgroup %u", info->invert ? " !" : "", info->id); +} + +static struct xtables_match cgroup_match = { + .family = NFPROTO_UNSPEC, + .name = "cgroup", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_cgroup_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_cgroup_info)), + .help = cgroup_help, + .print = cgroup_print, + .save = cgroup_save, + .x6_parse = cgroup_parse, + .x6_options = cgroup_opts, +}; + +void _init(void) +{ + xtables_register_match(&cgroup_match); +} diff --git a/extensions/libxt_cgroup.man b/extensions/libxt_cgroup.man new file mode 100644 index 00000000..456a0311 --- /dev/null +++ b/extensions/libxt_cgroup.man @@ -0,0 +1,15 @@ +.TP +[\fB!\fP] \fB\-\-cgroup\fP \fIfwid\fP +Match corresponding cgroup for this packet. + +Can be used to assign particular firewall policies for aggregated +task/jobs on the system. This allows for more fine-grained firewall +policies that only match for a subset of the system's processes. +fwid is the maker set through the net_cls cgroup's id. +.PP +Example: +.PP +iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-cgroup 1 +\-j DROP +.PP +Available since Linux 3.14. diff --git a/include/linux/netfilter/xt_cgroup.h b/include/linux/netfilter/xt_cgroup.h new file mode 100644 index 00000000..943d3a02 --- /dev/null +++ b/include/linux/netfilter/xt_cgroup.h @@ -0,0 +1,11 @@ +#ifndef _XT_CGROUP_H +#define _XT_CGROUP_H + +#include + +struct xt_cgroup_info { + __u32 id; + __u32 invert; +}; + +#endif /* _XT_CGROUP_H */ -- cgit v1.2.3