Messages in this thread Patch in this message | | | From | Jiri Slaby <> | Subject | [PATCH 05/15] connection tracking helper for SLP | Date | Tue, 7 May 2013 16:18:13 +0200 |
| |
From: Jiri Bohac <jbohac@suse.cz>
A simple connection tracking helper for SLP. Marks replies to a SLP broadcast query as ESTABLISHED to allow them to pass through the firewall.
Signed-off-by: Jiri Bohac <jbohac@suse.cz> Signed-off-by: Jiri Slaby <jslaby@suse.cz> Cc: netfilter-devel@vger.kernel.org Cc: netfilter@vger.kernel.org Cc: coreteam@netfilter.org Cc: netdev@vger.kernel.org Cc: "David S. Miller" <davem@davemloft.net> Cc: Patrick McHardy <kaber@trash.net> Cc: Pablo Neira Ayuso <pablo@netfilter.org> --- net/netfilter/Kconfig | 15 +++++ net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_slp.c | 131 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 net/netfilter/nf_conntrack_slp.c
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 56d22ca..ec61b30 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -320,6 +320,21 @@ config NF_CONNTRACK_TFTP To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_SLP + tristate "SLP protocol support" + depends on NF_CONNTRACK + depends on NETFILTER_ADVANCED + help + SLP queries are sometimes sent as broadcast messages from an + unprivileged port and responded to with unicast messages to the + same port. This make them hard to firewall properly because connection + tracking doesn't deal with broadcasts. This helper tracks locally + originating broadcast SLP queries and the corresponding + responses. It relies on correct IP address configuration, specifically + netmask and broadcast address. + + To compile it as a module, choose M here. If unsure, say N. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface' select NETFILTER_NETLINK diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index a1abf87..aa7d5f1 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o +obj-$(CONFIG_NF_CONNTRACK_SLP) += nf_conntrack_slp.o nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o diff --git a/net/netfilter/nf_conntrack_slp.c b/net/netfilter/nf_conntrack_slp.c new file mode 100644 index 0000000..0174dd0 --- /dev/null +++ b/net/netfilter/nf_conntrack_slp.c @@ -0,0 +1,131 @@ +/* + * NetBIOS name service broadcast connection tracking helper + * + * (c) 2007 Jiri Bohac <jbohac@suse.cz> + * (c) 2005 Patrick McHardy <kaber@trash.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +/* + * This helper tracks locally originating NetBIOS name service + * requests by issuing permanent expectations (valid until + * timing out) matching all reply connections from the + * destination network. The only NetBIOS specific thing is + * actually the port number. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/inetdevice.h> +#include <linux/if_addr.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/netfilter.h> +#include <net/route.h> + +#include <net/netfilter/nf_conntrack.h> +#include <net/netfilter/nf_conntrack_helper.h> +#include <net/netfilter/nf_conntrack_expect.h> + +#define SLP_PORT 427 + +MODULE_AUTHOR("Jiri Bohac <jbohac@suse.cz>"); +MODULE_DESCRIPTION("SLP broadcast connection tracking helper"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ip_conntrack_slp"); + +static unsigned int timeout __read_mostly = 3; +module_param(timeout, uint, 0400); +MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); + +static int help(struct sk_buff *skb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + struct nf_conntrack_expect *exp; + struct rtable *rt = skb_rtable(skb); + struct in_device *in_dev; + __be32 mask = 0; + __be32 src = 0; + + /* we're only interested in locally generated packets */ + if (skb->sk == NULL) + goto out; + if (rt == NULL || !(rt->rt_flags & (RTCF_MULTICAST|RTCF_BROADCAST))) + goto out; + if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) + goto out; + + rcu_read_lock(); + in_dev = __in_dev_get_rcu(rt->dst.dev); + if (in_dev != NULL) { + for_primary_ifa(in_dev) { + /* this is a hack as slp uses multicast we can't match + * the destination address to some broadcast address. So + * just take the first one. Better would be to install + * expectations for all addresses */ + mask = ifa->ifa_mask; + src = ifa->ifa_broadcast; + break; + } endfor_ifa(in_dev); + } + rcu_read_unlock(); + + if (mask == 0 || src == 0) + goto out; + + exp = nf_ct_expect_alloc(ct); + if (exp == NULL) + goto out; + + exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; + exp->tuple.src.u3.ip = src; + exp->tuple.src.u.udp.port = htons(SLP_PORT); + + exp->mask.src.u3.ip = mask; + exp->mask.src.u.udp.port = htons(0xFFFF); + + exp->expectfn = NULL; + exp->flags = NF_CT_EXPECT_PERMANENT; + exp->class = NF_CT_EXPECT_CLASS_DEFAULT; + exp->helper = NULL; + + nf_ct_expect_related(exp); + nf_ct_expect_put(exp); + + nf_ct_refresh(ct, skb, timeout * HZ); +out: + return NF_ACCEPT; +} + +static struct nf_conntrack_expect_policy exp_policy = { + .max_expected = 1, +}; + +static struct nf_conntrack_helper helper __read_mostly = { + .name = "slp", + .tuple.src.l3num = AF_INET, + .tuple.src.u.udp.port = __constant_htons(SLP_PORT), + .tuple.dst.protonum = IPPROTO_UDP, + .me = THIS_MODULE, + .help = help, + .expect_policy = &exp_policy, +}; + +static int __init nf_conntrack_slp_init(void) +{ + exp_policy.timeout = timeout; + return nf_conntrack_helper_register(&helper); +} + +static void __exit nf_conntrack_slp_fini(void) +{ + nf_conntrack_helper_unregister(&helper); +} + +module_init(nf_conntrack_slp_init); +module_exit(nf_conntrack_slp_fini); -- 1.8.2.1
| |