From 166b92d3fb2a7fc008df1b59332ef528a9a573ea Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 14 Jul 2011 23:56:47 +0200 Subject: extensions: add rpfilter module Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_rpfilter.c | 96 +++++++++++++++++++++++++++++++++++ extensions/libxt_rpfilter.man | 38 ++++++++++++++ include/linux/netfilter/xt_rpfilter.h | 17 +++++++ 3 files changed, 151 insertions(+) create mode 100644 extensions/libxt_rpfilter.c create mode 100644 extensions/libxt_rpfilter.man create mode 100644 include/linux/netfilter/xt_rpfilter.h diff --git a/extensions/libxt_rpfilter.c b/extensions/libxt_rpfilter.c new file mode 100644 index 00000000..168e703f --- /dev/null +++ b/extensions/libxt_rpfilter.c @@ -0,0 +1,96 @@ +#include +#include +#include + +enum { + O_RPF_LOOSE = 0, + O_RPF_VMARK = 1, + O_RPF_ACCEPT_LOCAL = 2, + O_RPF_INVERT = 3, +}; + +static void rpfilter_help(void) +{ + printf( +"rpfilter match options:\n" +" --loose permit reverse path via any interface\n" +" --validmark use skb nfmark when performing route lookup\n" +" --accept-local do not reject packets with a local source address\n" +" --invert match packets that failed the reverse path test\n" + ); +} + +static const struct xt_option_entry rpfilter_opts[] = { + {.name = "loose", .id = O_RPF_LOOSE, .type = XTTYPE_NONE, }, + {.name = "validmark", .id = O_RPF_VMARK, .type = XTTYPE_NONE, }, + {.name = "accept-local", .id = O_RPF_ACCEPT_LOCAL, .type = XTTYPE_NONE, }, + {.name = "invert", .id = O_RPF_INVERT, .type = XTTYPE_NONE, }, + XTOPT_TABLEEND, +}; + +static void rpfilter_parse(struct xt_option_call *cb) +{ + struct xt_rpfilter_info *rpfinfo = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_RPF_LOOSE: + rpfinfo->flags |= XT_RPFILTER_LOOSE; + break; + case O_RPF_VMARK: + rpfinfo->flags |= XT_RPFILTER_VALID_MARK; + break; + case O_RPF_ACCEPT_LOCAL: + rpfinfo->flags |= XT_RPFILTER_ACCEPT_LOCAL; + break; + case O_RPF_INVERT: + rpfinfo->flags |= XT_RPFILTER_INVERT; + break; + } +} + +static void +rpfilter_print_prefix(const void *ip, const void *matchinfo, + const char *prefix) +{ + const struct xt_rpfilter_info *info = matchinfo; + if (info->flags & XT_RPFILTER_LOOSE) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_LOOSE].name); + if (info->flags & XT_RPFILTER_VALID_MARK) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_VMARK].name); + if (info->flags & XT_RPFILTER_ACCEPT_LOCAL) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_ACCEPT_LOCAL].name); + if (info->flags & XT_RPFILTER_INVERT) + printf(" %s%s", prefix, rpfilter_opts[O_RPF_INVERT].name); +} + + +static void +rpfilter_print(const void *ip, const struct xt_entry_match *match, int numeric) +{ + printf(" rpfilter"); + return rpfilter_print_prefix(ip, match->data, ""); +} + +static void rpfilter_save(const void *ip, const struct xt_entry_match *match) +{ + return rpfilter_print_prefix(ip, match->data, "--"); +} + +static struct xtables_match rpfilter_match = { + .family = NFPROTO_UNSPEC, + .name = "rpfilter", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_rpfilter_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_rpfilter_info)), + .help = rpfilter_help, + .print = rpfilter_print, + .save = rpfilter_save, + .x6_parse = rpfilter_parse, + .x6_options = rpfilter_opts, +}; + +void _init(void) +{ + xtables_register_match(&rpfilter_match); +} diff --git a/extensions/libxt_rpfilter.man b/extensions/libxt_rpfilter.man new file mode 100644 index 00000000..aeb4a9d1 --- /dev/null +++ b/extensions/libxt_rpfilter.man @@ -0,0 +1,38 @@ +Performs a reverse path filter test on a packet. +If a reply to the packet would be sent via the same interface +that the packet arrived on, the packet will match. +Note that, unlike the in-kernel rp_filter, packets protected +by IPSec are not treated specially. Combine this match with +the policy match if you want this. +Also, packets arriving via the loopback interface are always permitted. +This match can only be used in the PREROUTING chain of the raw or mangle table. +.TP +\fB\-\-loose\fP +Used to specifiy that the reverse path filter test should match +even if the selected output device is not the expected one. +.TP +\fB\-\-validmark\fP +Also use the packets' nfmark value when performing the reverse path route lookup. +.TP +\fB\-\-accept\-local\fP +This will permit packets arriving from the network with a source address that is also +assigned to the local machine. +\fB\-\-invert\fP +This will invert the sense of the match. Instead of matching packets that passed the +reverse path filter test, match those that have failed it. +.PP +Example to log and drop packets failing the reverse path filter test: + +iptables \-t raw \-N RPFILTER + +iptables \-t raw \-A RPFILTER \-m rpfilter \-j RETURN + +iptables \-t raw \-A RPFILTER \-m limit \-\-limit 10/minute \-j NFLOG \-\-nflog\-prefix "rpfilter drop" + +iptables \-t raw \-A RPFILTER \-j DROP + +iptables \-t raw \-A PREROUTING \-j RPFILTER + +Example to drop failed packets, without logging: + +iptables \-t raw \-A RPFILTER \-m rpfilter \-\-invert \-j DROP diff --git a/include/linux/netfilter/xt_rpfilter.h b/include/linux/netfilter/xt_rpfilter.h new file mode 100644 index 00000000..672b6051 --- /dev/null +++ b/include/linux/netfilter/xt_rpfilter.h @@ -0,0 +1,17 @@ +#ifndef _XT_RPATH_H +#define _XT_RPATH_H + +#include + +enum { + XT_RPFILTER_LOOSE = 1 << 0, + XT_RPFILTER_VALID_MARK = 1 << 1, + XT_RPFILTER_ACCEPT_LOCAL = 1 << 2, + XT_RPFILTER_INVERT = 1 << 3, +}; + +struct xt_rpfilter_info { + __u8 flags; +}; + +#endif -- cgit v1.2.3