netfilter netbios-ns on ethernet bridge firewall

From: Jaco Kroon
Date: Sat Nov 12 2005 - 03:10:13 EST


Hello all,

I'm trying to make the ip_conntrack_netbios_ns module work on my
ethernet bridge firewall. The module works extremely nicely on a single
host when packets are locally generated, but doesn't even look at the
packets if they are generated elsewhere and merely pass through our box.

I'm currently running a vanilla kernel (2.6.14) with some of my own
printk statements and some minor modifications (diff below).

My configuration is essentially a device called br0 with eth0 and eth1
as it's two physical interfaces. I've got an IP of 192.168.0.4 assigned
to br0 (and an alias of 192.168.2.2), neither eth0 nor eth1 has an IP.

With the patch below applied when I send out a netbios-ns packet from
192.168.0.3 (coming in off eth0) I get the following in my logs:

Nov 12 09:38:17 xacatecas netbios packet seen
Nov 12 09:38:17 xacatecas sk is null
Nov 12 09:38:17 xacatecas rtable dst: 00000000
Nov 12 09:38:17 xacatecas rtable src: 00000000
Nov 12 09:38:17 xacatecas rtable iif: 00000000
Nov 12 09:38:17 xacatecas netbios packet seen
Nov 12 09:38:17 xacatecas sk is null
Nov 12 09:38:17 xacatecas rtable dst: ff00a8c0
Nov 12 09:38:17 xacatecas rtable src: 0300a8c0
Nov 12 09:38:17 xacatecas rtable iif: 00000004
Nov 12 09:38:17 xacatecas is a broadcast
Nov 12 09:38:17 xacatecas packet accepted!
Nov 12 09:38:17 xacatecas checking ...
Nov 12 09:38:17 xacatecas (lo) 00000000 vs ff00a8c0
Nov 12 09:38:17 xacatecas You almost certainly have a misconfigured
broadcast address.

>From what I understand the packet passes through the conntrack module
twice, once on PREROUTING and once on POSTROUTING, which is why the
first instance has rtable all zeroed. The second time round I expect to
see br0s details in the rtable, not lo though! The routing table looks
as follows:

Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt
Iface
192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 br0
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 br0
127.0.0.0 127.0.0.1 255.0.0.0 UG 0 0 0 lo
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 br0


In essense I've got two choices now:

1. Hardcode the mask as in the commented out mask = 0x00FFFFFF below,
which will only work for myself. (Or pass it as a parameter or
something - what happens in cases where the netmasks differ for multiple
interfaces?)

2. Cycle through the devices as provided by rtable, but also cycle
through _all_ inet devices. This would be more generic, but somehow I
don't think this is the correct solution, and it would eat a lot more CPU.

Thanks for any and all help/advice.

Jaco


--- net/ipv4/netfilter/ip_conntrack_netbios_ns.c.orig 2005-11-12
09:39:35.000000000 +0200
+++ net/ipv4/netfilter/ip_conntrack_netbios_ns.c 2005-11-12
09:33:18.000000000 +0200
@@ -50,32 +50,52 @@
u_int32_t mask = 0;

/* we're only interested in locally generated packets */
+ printk("netbios packet seen\n");
if ((*pskb)->sk == NULL)
- goto out;
+ printk("sk is null\n");
+ if (rt == NULL)
+ printk("rt == NULL!\n");
+ else {
+ printk("rtable dst: %08x\n", rt->rt_dst);
+ printk("rtable src: %08x\n", rt->rt_src);
+ printk("rtable iif: %08x\n", rt->rt_iif);
+ }
if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
goto out;
+ printk("is a broadcast\n");
if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
goto out;
-
+ printk("packet accepted!\n");
+
+// mask = 0x00FFFFFF;
rcu_read_lock();
in_dev = __in_dev_get_rcu(rt->u.dst.dev);
if (in_dev != NULL) {
+ printk("checking ...\n");
for_primary_ifa(in_dev) {
+ printk("(%s) %08x vs %08x\n", ifa->ifa_label,
ifa->ifa_broadcast, iph->daddr);
if (ifa->ifa_broadcast == iph->daddr) {
mask = ifa->ifa_mask;
- break;
+ printk(":)\n");
+// break;
}
} endfor_ifa(in_dev);
}
rcu_read_unlock();

- if (mask == 0)
+ if (mask == 0) {
+ printk(KERN_INFO "You almost certainly have a
misconfigured broadcast address.\n");
goto out;
+ }

+ printk("Yes, we are delivering to a local broadcast addr!\n");
+
exp = ip_conntrack_expect_alloc(ct);
if (exp == NULL)
goto out;

+ printk("We have managed to allocate an expect structure,
proceeding to add expect.\n");
+
exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
exp->tuple.src.u.udp.port = ntohs(NMBD_PORT);

--
There are only 10 kinds of people in this world,
those that understand binary and those that don't.
http://www.kroon.co.za/

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature