diff mbox

iptables: new strict host model match

Message ID 20090226175247.5e56910f@nehalam
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

stephen hemminger Feb. 27, 2009, 1:52 a.m. UTC
This is a simple little iptables match that can be used to create the Strong
End System model, that router and other non-Linux customers expect. There
are management and other applications that use ping and expect to only get
a response when the interface with that address is up. Normally, a Linux
system will respond to a packet that arrives for any of the system addresses
independent of which link it arrives on.

The module can be used on the INPUT chain like:

# iptables -P INPUT DROP
# iptables -A INPUT -m strict -j ACCEPT


---
 net/ipv4/devinet.c              |    1 
 net/ipv4/netfilter/Kconfig      |   12 ++++++++
 net/ipv4/netfilter/Makefile     |    1 
 net/ipv4/netfilter/ipt_strict.c |   56 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 70 insertions(+)

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Jan Engelhardt Feb. 27, 2009, 3:16 a.m. UTC | #1
On Friday 2009-02-27 02:52, Stephen Hemminger wrote:
>+static bool strict_mt(const struct sk_buff *skb, const struct xt_match_param *par)
>+{
>+	struct in_device *in_dev;
>+	bool ret;
>+
>+	rcu_read_lock();
>+	in_dev = __in_dev_get_rcu(skb->dev);
>+	ret = (in_dev && inet_addr_onlink(in_dev, ip_hdr(skb)->daddr, 0));
>+	rcu_read_unlock();
>+
>+	return ret;
>+}

This looks easy enough to also do for IPv6. Would you?

>+static struct xt_match strict_mt_reg __read_mostly = {
>+	.name		= "strict",
>+	.family		= NFPROTO_IPV4,
>+	.match		= strict_mt,
>+	.matchsize	= 0,
>+	.me		= THIS_MODULE,
>+};

The match seems to make the most sense where an input device
is available, so

	.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
	         (1 << NF_INET_FORWARD)

should probably be added.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
stephen hemminger Feb. 27, 2009, 3:23 a.m. UTC | #2
On Fri, 27 Feb 2009 04:16:19 +0100 (CET)
Jan Engelhardt <jengelh@medozas.de> wrote:

> 
> On Friday 2009-02-27 02:52, Stephen Hemminger wrote:
> >+static bool strict_mt(const struct sk_buff *skb, const struct xt_match_param *par)
> >+{
> >+	struct in_device *in_dev;
> >+	bool ret;
> >+
> >+	rcu_read_lock();
> >+	in_dev = __in_dev_get_rcu(skb->dev);
> >+	ret = (in_dev && inet_addr_onlink(in_dev, ip_hdr(skb)->daddr, 0));
> >+	rcu_read_unlock();
> >+
> >+	return ret;
> >+}
> 
> This looks easy enough to also do for IPv6. Would you?

IPV6 already does this.

> 
> >+static struct xt_match strict_mt_reg __read_mostly = {
> >+	.name		= "strict",
> >+	.family		= NFPROTO_IPV4,
> >+	.match		= strict_mt,
> >+	.matchsize	= 0,
> >+	.me		= THIS_MODULE,
> >+};
> 
> The match seems to make the most sense where an input device
> is available, so
> 
> 	.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
> 	         (1 << NF_INET_FORWARD)
> 
> should probably be added.

Then routing wouldn't work...
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jozsef Kadlecsik Feb. 27, 2009, 8:30 a.m. UTC | #3
On Thu, 26 Feb 2009, Stephen Hemminger wrote:

> On Fri, 27 Feb 2009 04:16:19 +0100 (CET)
> Jan Engelhardt <jengelh@medozas.de> wrote:
> 
> > This looks easy enough to also do for IPv6. Would you?
> 
> IPV6 already does this.

Still, it'd worth, because for example non-matching IPv4/IPv6 packets 
could then be logged together.

Best regards,
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlec@mail.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
          H-1525 Budapest 114, POB. 49, Hungary
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jan Engelhardt Feb. 28, 2009, 1:53 a.m. UTC | #4
On Friday 2009-02-27 04:23, Stephen Hemminger wrote:
>> >+static struct xt_match strict_mt_reg __read_mostly = {
>> >+	.name		= "strict",
>> >+	.family		= NFPROTO_IPV4,
>> >+	.match		= strict_mt,
>> >+	.matchsize	= 0,
>> >+	.me		= THIS_MODULE,
>> >+};
>> 
>> The match seems to make the most sense where an input device
>> is available, so
>> 
>> 	.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
>> 	         (1 << NF_INET_FORWARD)
>> 
>> should probably be added.
>
>Then routing wouldn't work...

How so?
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
stephen hemminger Feb. 28, 2009, 2:10 a.m. UTC | #5
On Sat, 28 Feb 2009 02:53:10 +0100 (CET)
Jan Engelhardt <jengelh@medozas.de> wrote:

> 
> On Friday 2009-02-27 04:23, Stephen Hemminger wrote:
> >> >+static struct xt_match strict_mt_reg __read_mostly = {
> >> >+	.name		= "strict",
> >> >+	.family		= NFPROTO_IPV4,
> >> >+	.match		= strict_mt,
> >> >+	.matchsize	= 0,
> >> >+	.me		= THIS_MODULE,
> >> >+};
> >> 
> >> The match seems to make the most sense where an input device
> >> is available, so
> >> 
> >> 	.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
> >> 	         (1 << NF_INET_FORWARD)
> >> 
> >> should probably be added.
> >
> >Then routing wouldn't work...
> 
I suppose it could be useful to to different chains for routed vs non-routed
packets on pre-routing chain, but on forward chain it wouldn't really
do anything useful.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jan Engelhardt Feb. 28, 2009, 8:27 a.m. UTC | #6
On Saturday 2009-02-28 03:10, Stephen Hemminger wrote:
>> On Friday 2009-02-27 04:23, Stephen Hemminger wrote:
>> >> >+static struct xt_match strict_mt_reg __read_mostly = {
>> >> >+	.name		= "strict",
>> >> >+	.family		= NFPROTO_IPV4,
>> >> >+	.match		= strict_mt,
>> >> >+	.matchsize	= 0,
>> >> >+	.me		= THIS_MODULE,
>> >> >+};
>> >> 
>> >> The match seems to make the most sense where an input device
>> >> is available, so
>> >> 
>> >> 	.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) |
>> >> 	         (1 << NF_INET_FORWARD)
>> >> 
>> >> should probably be added.
>> >
>> >Then routing wouldn't work...
>> 
>I suppose it could be useful to to different chains for routed vs non-routed
>packets on pre-routing chain, but on forward chain it wouldn't really
>do anything useful.
>
...Ok? The hooks mask limits the use of the match to - true to its name -
hooks, so it is implies permitting the use of the match in the
PREROUTING/INPUT/FORWARD chain and chains called from it, as long as
no unlisted chain has a reference to it too. This is how most other
modules, e.g. xt_mac, act too.

Since xt_strict inspects in_dev, and in_dev is not available in
OUTPUT/POSTROUTING, I was suggesting to just limit its use to the
chains where in_dev != NULL.
Or did I misunderstood you?
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick McHardy March 2, 2009, 11:02 a.m. UTC | #7
Stephen Hemminger wrote:
> This is a simple little iptables match that can be used to create the Strong
> End System model, that router and other non-Linux customers expect. There
> are management and other applications that use ping and expect to only get
> a response when the interface with that address is up. Normally, a Linux
> system will respond to a packet that arrives for any of the system addresses
> independent of which link it arrives on.
> 
> The module can be used on the INPUT chain like:
> 
> # iptables -P INPUT DROP
> # iptables -A INPUT -m strict -j ACCEPT

The idea makes sense ..

> +static bool strict_mt(const struct sk_buff *skb, const struct xt_match_param *par)
> +{
> +	struct in_device *in_dev;
> +	bool ret;
> +
> +	rcu_read_lock();
> +	in_dev = __in_dev_get_rcu(skb->dev);
> +	ret = (in_dev && inet_addr_onlink(in_dev, ip_hdr(skb)->daddr, 0));
> +	rcu_read_unlock();
> +
> +	return ret;
> +}

I'm not sure this is correct, I think it will only allow communication
with truely on-link addresses, meaning it won't accept routed packets
going to the interface address. Generally I don't think this can be
fully done in iptables since you'd still have to deal with ARP etc.
An IPv4 sysctl might be more appropriate.

Just for the IPv4 packets, I'm wondering if the intended result could
be achieved using the addrtype match. Something like:

-m addrtype --limit-iface-in --dst-type LOCAL

should check whether the destination address is local to the receiving
interface.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jesper Dangaard Brouer March 2, 2009, 1:42 p.m. UTC | #8
On Thu, 26 Feb 2009, Stephen Hemminger wrote:

> This is a simple little iptables match that can be used to create the Strong
> End System model, that router and other non-Linux customers expect. There
> are management and other applications that use ping and expect to only get
> a response when the interface with that address is up. Normally, a Linux
> system will respond to a packet that arrives for any of the system addresses
> independent of which link it arrives on.

Is this no almost the same as:

  echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore



> +static bool strict_mt(const struct sk_buff *skb, const struct xt_match_param *par)
> +{
> +	struct in_device *in_dev;
> +	bool ret;
> +
> +	rcu_read_lock();
> +	in_dev = __in_dev_get_rcu(skb->dev);
> +	ret = (in_dev && inet_addr_onlink(in_dev, ip_hdr(skb)->daddr, 0));

inet_addr_onlink() will call
  -> inet_ifa_match(ip_hdr(skb)->daddr, ifa)

arp_ignore = 1
  -> inet_confirm_addr(in_dev, 0, tip, RT_SCOPE_HOST)
     -> inet_ifa_match(tip, ifa)


Hilsen
   Jesper Brouer

--
-------------------------------------------------------------------
MSc. Master of Computer Science
Dept. of Computer Science, University of Copenhagen
Author of http://www.adsl-optimizer.dk
-------------------------------------------------------------------
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Denys Fedoryshchenko March 2, 2009, 1:46 p.m. UTC | #9
On Monday 02 March 2009 15:42:33 Jesper Dangaard Brouer wrote:
> On Thu, 26 Feb 2009, Stephen Hemminger wrote:
> > This is a simple little iptables match that can be used to create the
> > Strong End System model, that router and other non-Linux customers
> > expect. There are management and other applications that use ping and
> > expect to only get a response when the interface with that address is up.
> > Normally, a Linux system will respond to a packet that arrives for any of
> > the system addresses independent of which link it arrives on.
>
> Is this no almost the same as:
>
>   echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
>
I guess if some "smart guy" will set static association in his ARP table, he 
can ignore this rule and "hack the host" over another ip, which sits on 
internal interface for example.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
stephen hemminger March 2, 2009, 6:53 p.m. UTC | #10
On Mon, 2 Mar 2009 14:42:33 +0100 (CET)
Jesper Dangaard Brouer <hawk@diku.dk> wrote:

> On Thu, 26 Feb 2009, Stephen Hemminger wrote:
> 
> > This is a simple little iptables match that can be used to create the Strong
> > End System model, that router and other non-Linux customers expect. There
> > are management and other applications that use ping and expect to only get
> > a response when the interface with that address is up. Normally, a Linux
> > system will respond to a packet that arrives for any of the system addresses
> > independent of which link it arrives on.
> 
> Is this no almost the same as:
> 
>   echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
> 
>

That doesn't work when system already has an ARP entry and link goes down.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick McHardy March 2, 2009, 10:12 p.m. UTC | #11
Stephen Hemminger wrote:
> On Mon, 2 Mar 2009 14:42:33 +0100 (CET)
> Jesper Dangaard Brouer <hawk@diku.dk> wrote:
> 
>> On Thu, 26 Feb 2009, Stephen Hemminger wrote:
>>
>>> This is a simple little iptables match that can be used to create the Strong
>>> End System model, that router and other non-Linux customers expect. There
>>> are management and other applications that use ping and expect to only get
>>> a response when the interface with that address is up. Normally, a Linux
>>> system will respond to a packet that arrives for any of the system addresses
>>> independent of which link it arrives on.
>> Is this no almost the same as:
>>
>>   echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
>>
>>
> 
> That doesn't work when system already has an ARP entry and link goes down.

I think it would make sense to define the differences in behaviour
that are expected when acting according to the strict host model.
It very unlikely that all of this can be achieved with iptables,
and if what can be done is still useful, the limitations should be
known.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

--- a/net/ipv4/netfilter/Kconfig	2009-02-26 17:47:03.000000000 -0800
+++ b/net/ipv4/netfilter/Kconfig	2009-02-26 17:47:08.000000000 -0800
@@ -92,6 +92,18 @@  config IP_NF_MATCH_ECN
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_MATCH_STRICT
+       tristate '"strict end system" match support'
+	depends on NETFILTER_ADVANCED
+	help
+	  This option adds a 'strict' match, which allows you to
+	  match only packets that arrive with the destinaton address matching
+	  an IP address on the incoming interface. This can be used to implement
+	  Strong End System model as defined in Internet Host Requirements
+	  (RFC1122).
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_MATCH_TTL
 	tristate '"ttl" match support'
 	depends on NETFILTER_ADVANCED
--- a/net/ipv4/netfilter/Makefile	2009-02-26 17:46:37.000000000 -0800
+++ b/net/ipv4/netfilter/Makefile	2009-02-26 17:47:08.000000000 -0800
@@ -51,6 +51,7 @@  obj-$(CONFIG_IP_NF_SECURITY) += iptable_
 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
+obj-$(CONFIG_IP_NF_MATCH_STRICT) += ipt_strict.o
 
 # targets
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
--- a/net/ipv4/devinet.c	2009-02-26 17:46:37.000000000 -0800
+++ b/net/ipv4/devinet.c	2009-02-26 17:47:08.000000000 -0800
@@ -230,6 +230,7 @@  int inet_addr_onlink(struct in_device *i
 	rcu_read_unlock();
 	return 0;
 }
+EXPORT_SYMBOL_GPL(inet_addr_onlink);
 
 static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
 			 int destroy, struct nlmsghdr *nlh, u32 pid)
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ b/net/ipv4/netfilter/ipt_strict.c	2009-02-26 17:52:19.000000000 -0800
@@ -0,0 +1,56 @@ 
+/* IP tables module for matching packets not routed to incoming interface
+ *
+ * (C) 2009 by Stephen Hemminger <shemminger@vyatta.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if.h>
+#include <linux/inetdevice.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+MODULE_AUTHOR("Stephen Hemminger <shemminger@vyatta.com>");
+MODULE_DESCRIPTION("Xtables: Strict End System match");
+MODULE_LICENSE("GPL");
+
+static bool strict_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+	struct in_device *in_dev;
+	bool ret;
+
+	rcu_read_lock();
+	in_dev = __in_dev_get_rcu(skb->dev);
+	ret = (in_dev && inet_addr_onlink(in_dev, ip_hdr(skb)->daddr, 0));
+	rcu_read_unlock();
+
+	return ret;
+}
+
+static struct xt_match strict_mt_reg __read_mostly = {
+	.name		= "strict",
+	.family		= NFPROTO_IPV4,
+	.match		= strict_mt,
+	.matchsize	= 0,
+	.me		= THIS_MODULE,
+};
+
+static int __init strict_mt_init(void)
+{
+	return xt_register_match(&strict_mt_reg);
+}
+
+static void __exit strict_mt_exit(void)
+{
+	xt_unregister_match(&strict_mt_reg);
+}
+
+module_init(strict_mt_init);
+module_exit(strict_mt_exit);