Skip to contentSkip to conversation

Route match v2

RFC PATCH In review Phil Oester 2 participants 4 messages Jul 4, 2008 – Jul 7, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 Route match v2

Attached is a new "route" match, which matches against entries in the kernel routing table.

Changes since v1:
* IPv6 support in kernel
* Invert support for ALL options
* Various cleanup in userspace code (C99 initializers & unified v4/v6 parse)

I've tested the IPv6 support as best I can, but I'd appreciate someone who actually has production v6 nets giving it a run through.

Options:

[!] --route-src-exists      Route for src exists
[!] --route-src-eq value    Route for src exists with prefix-length == value
[!] --route-src-gt value    Route for src exists with prefix-length  > value
[!] --route-src-lt value    Route for src exists with prefix-length  < value
[!] --route-dst-exists      Route for dst exists
[!] --route-dst-eq value    Route for dst exists with prefix-length == value
[!] --route-dst-gt value    Route for dst exists with prefix-length  > value
[!] --route-dst-lt value    Route for dst exists with prefix-length  < value

Examples:

Egress filtering (similar to rp_filter, but not silently dropped):
iptables -N spoofer -j LOG --log-prefix "Spoofed packet dropped: " iptables -N spoofer -j DROP
iptables -A FORWARD -i $INTERNAL_IF -m route ! --route-src-exists -j spoofer

rp_filter functionality on IPv6:
ip6tables -A FORWARD -i $EXTERNAL_IF -m route --route-src-exists -j DROP

Allow a user to only browse internal websites:
iptables -A FORWARD -p tcp --dport 80 -m route --route-dst-exists -j ACCEPT

Allow an SNMP collector to reach all internal routers (/30 or /32)
iptables -A FORWARD -p udp --dport 161 -m route --route-dst-gt 29 -j ACCEPT

Comments?

Phil

include/linux/netfilter/xt_route.h new file +21 -0
new file mode 100644
index 0000000..0c90494
@@ -0,0 +1,21 @@
+#ifndef _XT_ROUTE_H
+#define _XT_ROUTE_H
+
+enum {
+	XT_ROUTE_SRC_EXISTS = 0,
+	XT_ROUTE_SRC_EQ,
+	XT_ROUTE_SRC_GT,
+	XT_ROUTE_SRC_LT,
+	XT_ROUTE_DST_EXISTS,
+	XT_ROUTE_DST_EQ,
+	XT_ROUTE_DST_GT,
+	XT_ROUTE_DST_LT,
+};
+
+struct xt_route_info {
+	u_int8_t	invert;
+	u_int8_t	mode;
+	u_int8_t	prefixlen;
+};
+
+#endif /*_XT_ROUTE_H*/
net/ipv4/fib_semantics.c +2 -0
index 0d4d728..22bbdd5 100644
@@ -156,6 +156,8 @@ void free_fib_info(struct fib_info *fi)
 	kfree(fi);
 }
 
+EXPORT_SYMBOL_GPL(free_fib_info);
+
 void fib_release_info(struct fib_info *fi)
 {
 	spin_lock_bh(&fib_info_lock);
net/ipv6/ip6_fib.c +2 -0
index 1ee4fa1..5d6419f 100644
@@ -897,6 +897,8 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr,
 	return fn;
 }
 
+EXPORT_SYMBOL_GPL(fib6_lookup);
+
 /*
  *	Get node with specified destination prefix (and source prefix,
  *	if subtrees are used)
net/netfilter/Kconfig +10 -0
index aa8d80c..128b186 100644
@@ -724,6 +724,16 @@ config NETFILTER_XT_MATCH_REALM
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_MATCH_ROUTE
+	tristate '"route" match support'
+	depends on NETFILTER_XTABLES
+	depends on NETFILTER_ADVANCED
+	help
+	  This option adds a `route' match, which allows you to match on
+	  the kernel routing table.  
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_SCTP
 	tristate  '"sctp" protocol match support (EXPERIMENTAL)'
 	depends on NETFILTER_XTABLES && EXPERIMENTAL
net/netfilter/Makefile +1 -0
index 5c4b183..1035372 100644
@@ -76,6 +76,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_ROUTE) += xt_route.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
net/netfilter/xt_route.c new file +197 -0

197 lines not on this page · raw message

extensions/libxt_route.c new file +267 -0

267 lines not on this page · raw message

include/linux/netfilter/xt_route.h new file +21 -0
new file mode 100644
index 0000000..0c90494
@@ -0,0 +1,21 @@
+#ifndef _XT_ROUTE_H
+#define _XT_ROUTE_H
+
+enum {
+	XT_ROUTE_SRC_EXISTS = 0,
+	XT_ROUTE_SRC_EQ,
+	XT_ROUTE_SRC_GT,
+	XT_ROUTE_SRC_LT,
+	XT_ROUTE_DST_EXISTS,
+	XT_ROUTE_DST_EQ,
+	XT_ROUTE_DST_GT,
+	XT_ROUTE_DST_LT,
+};
+
+struct xt_route_info {
+	u_int8_t	invert;
+	u_int8_t	mode;
+	u_int8_t	prefixlen;
+};
+
+#endif /*_XT_ROUTE_H*/
#1 lore raw
Quoted 17 lines · Phil Oester

Attached is a new "route" match, which matches against entries in the kernel routing table.

Changes since v1:
* IPv6 support in kernel
* Invert support for ALL options
* Various cleanup in userspace code (C99 initializers & unified v4/v6 parse)

I've tested the IPv6 support as best I can, but I'd appreciate someone who actually has production v6 nets giving it a run through.

net/netfilter/xt_route.c new file +5 -0
+static bool
+route_mt6(const struct sk_buff *skb, const struct net_device *in,
+           const struct net_device *out, const struct xt_match *match,
+           const void *matchinfo, int offset, unsigned int protoff,
+           bool *hotdrop)

net/netfilter/xt_route.c line 119

Quoted 10 lines
net/netfilter/xt_route.c new file +10 -0
+{
+	const struct xt_route_info *info = matchinfo;
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct fib6_node *fn;
+	struct flowi fl = {0};
+
+	switch (info->mode) {
+	case XT_ROUTE_SRC_EXISTS:
+		fl.nl_u.ip6_u.daddr = iph->saddr;
+		fn = fib6_lookup(&dev_net(in)->ipv6.fib6_main_tbl->tb6_root, &fl.fl6_dst, NULL);

This is always using the main table, which is inconsistent with the IPv4 support. It also shouldn't call IPv6 functions directly to avoid incorrect module dependencies.

#2 lore raw
Quoted 11 lines · Patrick McHardy
Quoted 11 lines
net/netfilter/xt_route.c new file +11 -0
+static bool
+route_mt6(const struct sk_buff *skb, const struct net_device *in,
+           const struct net_device *out, const struct xt_match *match,
+           const void *matchinfo, int offset, unsigned int protoff,
+           bool *hotdrop)
+{
+	const struct xt_route_info *info = matchinfo;
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct fib6_node *fn;
+	struct flowi fl = {0};
+
Quoted 8 lines

net/netfilter/xt_route.c line 119

Quoted 4 lines
net/netfilter/xt_route.c new file +4 -0
+	switch (info->mode) {
+	case XT_ROUTE_SRC_EXISTS:
+		fl.nl_u.ip6_u.daddr = iph->saddr;
+		fn = fib6_lookup(&dev_net(in)->ipv6.fib6_main_tbl->tb6_root, &fl.fl6_dst, NULL);

This is always using the main table, which is inconsistent with the IPv4 support. It also shouldn't call IPv6 functions directly to avoid incorrect module dependencies.

What are the alternatives? If we need to support IPv6 in the match, then we need to call the functions directly, no? Is there a helper function I'm missing?

Phil

#3 lore raw
Quoted 20 lines · Phil Oester
Quoted 10 lines · Patrick McHardy
Quoted 10 lines
net/netfilter/xt_route.c new file +10 -0
+static bool
+route_mt6(const struct sk_buff *skb, const struct net_device *in,
+           const struct net_device *out, const struct xt_match *match,
+           const void *matchinfo, int offset, unsigned int protoff,
+           bool *hotdrop)
+{
+	const struct xt_route_info *info = matchinfo;
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	struct fib6_node *fn;
+	struct flowi fl = {0};
Quoted 8 lines

net/netfilter/xt_route.c line 119

Quoted 5 lines
net/netfilter/xt_route.c new file +5 -0
+
+	switch (info->mode) {
+	case XT_ROUTE_SRC_EXISTS:
+		fl.nl_u.ip6_u.daddr = iph->saddr;
+		fn = fib6_lookup(&dev_net(in)->ipv6.fib6_main_tbl->tb6_root, &fl.fl6_dst, NULL);

This is always using the main table, which is inconsistent with the IPv4 support. It also shouldn't call IPv6 functions directly to avoid incorrect module dependencies.

Quoted 3 lines

What are the alternatives? If we need to support IPv6 in the match, then we need to call the functions directly, no? Is there a helper function I'm missing?

There are the ->route functions is nf_afinfo, but I'm not sure if they will work for you. You may have too add some new ones.