Skip to contentSkip to conversation

address type match limited to incoming interface

PATCH Superseded Laszlo Attila Toth 2 participants 7 messages Oct 12, 2007 – Oct 20, 2007

Subsystems (3)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

cover address type match limited to incoming interface

Hello,

Current version of address type match lets incoming packets filter by address type such as LOCAL (local address of any interface). With this the following patches this type check can be limited to the interface the packet coming in. For instance the lets SSH in on every interface and nothing else:

iptables -P INPUT DROP
(some additional checks may be here such as -m state --state INVALID -j DROP)
iptables -A INPUT -p tcp -m tcp --dport 22 -m addrtype --dst-type LOCAL --limit-iface -j ACCEPT

If a packet arrives on eth0 with the IP address of the eth0 it is accepted but if it is an address of eth1 it is dropped.

Also it can be used for checking IP spoofing.

Regards,
Attila

#1 lore raw

PATCH 1/2 Find address type on a specific or on any interface

From: Tóth László Attila <[email protected]>

Address type search can be limited to any interface by inet_addr_type_on_dev function.

---
 include/net/route.h     |    1 +
 net/ipv4/fib_frontend.c |   21 +++++++++++++++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)
include/net/route.h +1 -0
index f7ce625..4a0e3bc 100644
@@ -119,6 +119,7 @@ extern unsigned short	ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mt
 extern void		ip_rt_send_redirect(struct sk_buff *skb);
 
 extern unsigned		inet_addr_type(__be32 addr);
+extern unsigned		inet_addr_type_on_dev(__be32 addr, const struct net_device *on_dev);
 extern void		ip_rt_multicast_event(struct in_device *);
 extern int		ip_rt_ioctl(unsigned int cmd, void __user *arg);
 extern void		ip_rt_get_source(u8 *src, struct rtable *rt);
net/ipv4/fib_frontend.c +19 -2
index eff6bce..9d93a20 100644
@@ -145,7 +145,11 @@ out:
 	return dev;
 }
 
-unsigned inet_addr_type(__be32 addr)
+/*
+ * Find address type as if only "on_dev" was present in the system. If
+ * on_dev is NULL then all interfaces are taken into consideration.
+ */
+static inline unsigned __inet_addr_type_on_dev(__be32 addr, const struct net_device *on_dev)
 {
 	struct flowi		fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
 	struct fib_result	res;
@@ -164,13 +168,25 @@ unsigned inet_addr_type(__be32 addr)
 		ret = RTN_UNICAST;
 		if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
 						   &fl, &res)) {
-			ret = res.type;
+			if ((!on_dev || on_dev == res.fi->fib_dev)) {
+			        ret = res.type;
+			}
 			fib_res_put(&res);
 		}
 	}
 	return ret;
 }
 
+unsigned inet_addr_type(__be32 addr)
+{
+  return __inet_addr_type_on_dev(addr, NULL);
+}
+
+unsigned inet_addr_type_on_dev(__be32 addr, const struct net_device *on_dev)
+{
+  return __inet_addr_type_on_dev(addr, on_dev);
+}
+
 /* Given (packet source, input interface) and optional (dst, oif, tos):
    - (main) check, that source is valid i.e. not broadcast or our local
      address.
@@ -922,4 +938,5 @@ void __init ip_fib_init(void)
 }
 
 EXPORT_SYMBOL(inet_addr_type);
+EXPORT_SYMBOL(inet_addr_type_on_dev);
 EXPORT_SYMBOL(ip_dev_find);
Signature · 6 lines
1.5.2.5

-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#2 lore raw

PATCH 2/2 Addrtype match extension: limit addrtype check on the packet's interface

From: Tóth László Attila <[email protected]>

Addrtype match has a new revision (1), which lets address type checking limit to the interface the current packet belongs to.

Revision 0 lets older userspace programs use the match as earlier.

---
 include/linux/netfilter_ipv4/ipt_addrtype.h |   15 +++++++
 net/ipv4/netfilter/ipt_addrtype.c           |   59 ++++++++++++++++++++-------
 2 files changed, 59 insertions(+), 15 deletions(-)
include/linux/netfilter_ipv4/ipt_addrtype.h +15 -0
index 166ed01..019ab47 100644
@@ -1,9 +1,24 @@
 #ifndef _IPT_ADDRTYPE_H
 #define _IPT_ADDRTYPE_H
 
+#define IPT_ADDRTYPE_REVISION        0x0001
+
+enum
+{
+	IPT_ADDRTYPE_INVERT_SOURCE = 0x0001,
+	IPT_ADDRTYPE_INVERT_DEST   = 0x0002,
+	IPT_ADDRTYPE_LIMIT_IFACE   = 0x0004,
+};
+
 struct ipt_addrtype_info {
 	u_int16_t	source;		/* source-type mask */
 	u_int16_t	dest;		/* dest-type mask */
+	u_int32_t       flags;
+};
+
+struct ipt_addrtype_info_v0 {
+	u_int16_t	source;		/* source-type mask */
+	u_int16_t	dest;		/* dest-type mask */
 	u_int32_t	invert_source;
 	u_int32_t	invert_dest;
 };
net/ipv4/netfilter/ipt_addrtype.c +44 -15

88 lines not on this page · raw message

Signature · 6 lines
1.5.2.5

-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw

Re: [PATCH 2/2] Addrtype match extension: limit addrtype check on the packet's interface

net/ipv4/netfilter/ipt_addrtype.c MODULE_LICENSE("GPL"); · line 54

Quoted 8 lines · Laszlo Attila Toth
net/ipv4/netfilter/ipt_addrtype.c +2 -0
+static bool match_v1(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 ipt_addrtype_info *info = matchinfo;
 	const struct iphdr *iph = ip_hdr(skb);
+	const struct net_device *limit_dev = (info->flags & IPT_ADDRTYPE_LIMIT_IFACE) ? in : NULL;

The match can be used on any hook, using the incoming interface is a bit unflexible. How about using the incoming interface for src-address and outgoing interface for destination address matches? Alternatively add two flags to specify which device to use. You'll need to add proper checks of course to make sure the interface is valid for the hook the match is used in.

#4 lore raw

Re: [PATCH 2/2] Addrtype match extension: limit addrtype check on the packet's interface

Patrick McHardy írta:

Quoted 12 lines
Quoted 9 lines · Laszlo Attila Toth
net/ipv4/netfilter/ipt_addrtype.c +2 -0
+static bool match_v1(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 ipt_addrtype_info *info = matchinfo;
     const struct iphdr *iph = ip_hdr(skb);
+    const struct net_device *limit_dev = (info->flags & 

IPT_ADDRTYPE_LIMIT_IFACE) ? in : NULL;

Quoted 6 lines

The match can be used on any hook, using the incoming interface is a bit unflexible. How about using the incoming interface for src-address and outgoing interface for destination address matches? Alternatively add two flags to specify which device to use. You'll need to add proper checks of course to make sure the interface is valid for the hook the match is used in.

Two flags would be better because the forward chain can be handled specially. For all the others two different options arn't necessary. In the forward chain both src and the dst addrtypes would be checked twice in this case, once on the input interface and once on the output.

Signature · 5 lines
Attila
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#5 lore raw

Re: [PATCH 2/2] Addrtype match extension: limit addrtype check on the packet's interface

In reply to Patrick McHardy

Patrick McHardy írta:

Quoted 12 lines
Quoted 9 lines · Laszlo Attila Toth
net/ipv4/netfilter/ipt_addrtype.c +2 -0
+static bool match_v1(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 ipt_addrtype_info *info = matchinfo;
     const struct iphdr *iph = ip_hdr(skb);
+    const struct net_device *limit_dev = (info->flags & 

IPT_ADDRTYPE_LIMIT_IFACE) ? in : NULL;

Quoted 3 lines

The match can be used on any hook, using the incoming interface is a bit unflexible. How about using the incoming interface for src-address and outgoing interface for destination address matches?

But what happens when I use only dst-type in the rule in the INPUT chain?

I think in the INPUT chain the incoming interface with the dst-type and in the OUTPUT chain the outgoing interface with the src-type parameter could be used. And what should I check in the other 3 chains? In FORWARD it seems pointless to let the limit-iface option.

Quoted 3 lines

Alternatively add two flags to specify which device to use. You'll need to add proper checks of course to make sure the interface is valid for the hook the match is used in.

Hm, I need a hooknum parameter in the match function which exists only in the target functions.

Signature · 5 lines
Attila
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#6 lore raw

Re: [PATCH 1/2] Find address type on a specific or on any interface

In reply to Laszlo Attila Toth

net/ipv4/fib_frontend.c out: · line 152

Quoted 5 lines · Laszlo Attila Toth
net/ipv4/fib_frontend.c +5 -0
+/*
+ * Find address type as if only "on_dev" was present in the system. If
+ * on_dev is NULL then all interfaces are taken into consideration.
+ */
+static inline unsigned __inet_addr_type_on_dev(__be32 addr, const struct net_device *on_dev)

I would prefer the name "__inet_dev_addr_type" or "__dev_inet_addr_type"

net/ipv4/fib_frontend.c unsigned inet_addr_type(__be32 addr) · line 173

Quoted 11 lines

{

net/ipv4/fib_frontend.c +3 -1
 	struct flowi		fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
 	struct fib_result	res;
@@ -164,13 +168,25 @@ unsigned inet_addr_type(__be32 addr)
 		ret = RTN_UNICAST;
 		if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
 						   &fl, &res)) {
-			ret = res.type;
+			if ((!on_dev || on_dev == res.fi->fib_dev)) {
+			        ret = res.type;
+			}

No braces around single statements that fit on one line please.

net/ipv4/fib_frontend.c unsigned inet_addr_type(__be32 addr) · line 182

Quoted 9 lines
net/ipv4/fib_frontend.c +3 -0
 			fib_res_put(&res);
 		}
 	}
 	return ret;
 }
 
+unsigned inet_addr_type(__be32 addr)
+{
+  return __inet_addr_type_on_dev(addr, NULL);

Use tabs for indenting.