Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Jul 2007 02:44:22 +1000 (EST)
From:      Ian Smith <smithi@nimnet.asn.au>
To:        Dave McCammon <davemac11@yahoo.com>
Cc:        stable@freebsd.org
Subject:   Re: ipfw with if_bridge oddity
Message-ID:  <Pine.BSF.3.96.1070711235853.13605A-100000@gaia.nimnet.asn.au>
In-Reply-To: <630256.41139.qm@web32806.mail.mud.yahoo.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 10 Jul 2007, Dave McCammon wrote:

 > On Fri, 6 Jul 2007, Dave McCammon wrote:

Well, quoting me at the first level; I know, but others mightn't ..

 >  > I can't seem to grasp why this is working differently.
 >  > FreeBSD 6.2 using ipfw + if_bridge
 >  > 
 >  > LAN -- em1(if_bridge + ipfw)em0 -- internet
 >  > 
 >  > I am at xx.xx.16.6 and try to ping say www.yahoo.com
 >  > 
 >  > in ruleset:
 >  > 1100 allow icmp from any to xx.xx.16.0/27{1-10,13,14,19,22,23} icmptypes 0,3,11,12,13,14
 >  > 2100 allow ip from xx.xx.16.0/27 to any in via em1
 > 
 > >Seeing noone more knowledgeable has had a go, and with the caveat that
 > Thank you.
 > 
 > >I've never setup an if_bridge(4) but still maintain a bridge(4)+ipfw ..
 > 
 > >Rule 2100 lets your ping in, and 1100 allows the response (in and out)
 > 
 >  > gets dropped by following rule as shown in logs:
 >  > 
 >  > 4700 deny log ip from any to any
 >  > 
 >  > Log entry: ipfw: 4700 Deny ICMP:8.0 xx.xx.16.6 69.147.114.210 out via em0
 > 
 > >Denied because you have no rule letting it go out, it seems.
 > 
 > It's the "out via em0" that I am questioning, which I believe shouldn't be happening.

Well if I'm right about if_bridge(4) also examining outbound packets, ie
if I'm reading the manual right, and referring to PACKET FLOW in ipfw(8) 
- rather than bridge(4) which only examined inbound bridged packets -
then it makes sense that these would be denied, since you haven't
allowed them out, which you need to do .. 

 > It seems that ipfw+if_bridge works differently with ICMP than ipfw_bridge(4).

I don't think your problem is ICMP-specific (though this instance is).

 > Rule 2100 should allow the packet through(I read the rule as:"it is ok since it came in em1").

No; if you specify in or out, only packets coming in (to the firewall,
first pass) or on the way out (from the firewall, second pass) match the
rule, which is how it's always been with routing, though not with older
bridge(4)

If you don't specify in or out, rules match on either and both passes,
your rule 1100 for instance ..

 > Other rules just like this(in via em1) work with tcp and udp. 
 > example :
 >     allow tcp from xx.xx.16.0/27 to any in via em1 setup keep-state
 >     if the packet came from xx.xx.16.0/27 network and came "in" the em1 interface,
 >     than pass the packet.

Then pass the packet _coming in_, as you specified 'in'.  In this case
it's a keep-state rule, which I suspect must be allowing it out also,
though I must admit to being a bit hazy about stateful rule handling. 
It can also be tricky not having seen the entire ruleset.

But your icmp rule is stateless, so needs to be let pass also outbound,
otherwise it is (and was, as we saw!) denied.

You could try keep-state on the icmp rule (though rearranged to allow
your guys to send icmptypes to any) , or you could add a rule to allow
it on the out pass (eg, out xmit em0), or you could just drop the 'in'
on rule 2100 (assuming you've got anti-spoofing rules covering em0)

 > It just seems the ICMP gets dropped,
 > which, I am assuming, rule 2100 should have allowed through the firewall.

See above; not through, but only into, with your sysctls.

 >  > If I add this rule all works great:
 >  > 
 >  > 2101 allow icmp from xx.xx.16.0/27 to any recv em1
 > 
 > >Which allows it both in and out (neither specified)
 > 
 > This should allow the packet because it came through the receiving interface on interface em1.

Yes, but it a) allows it 'in' on the first pass, then allows it 'out' on
the second.  With bridge(4), once it was allowed in, it went out without
any second pass.  This seems (and is said) to be not so with if_bridge,
the way you've configured the sysctls below anyway.

 > This is really my questioning: Why is it that "in via em1" doesn't work on ICMP but changing or adding
 > a similar rule with "recv em1" will pass the ICMP.
 >     allow ip from 157.91.16.0/27 to any in via em1  >  legit "passing_thru" ICMP gets dropped with if_bridge but not with bridge(4)
 >     allow ip from 157.91.16.0/27 to any recv em1 > passes the "passing_thru" ICMP using if_bridge

The first specifies 'in', and so only matches the first, inbound, pass. 

The second specifies neither 'in' nor 'out', so matches on BOTH passes; 
you can match the recv iface on both inbound and outbound packet rules,
though only 'out' rules can specify the xmit iface (ie after routing or
in this case bridging has been done, where the xmit iface is now known). 

Chew on ipfw(8) section "recv | xmit | via {ifX | if* | ipno | any}" 

 >  > Why would the "recv em1" work and the "in via em1" get blocked?

See above.  Sorry if I'm repeating myself too much, but don't confuse
'in' and 'out' packets with 'recv', 'xmit' or 'via' specifying ifaces.

 >  > I just changed from using bridge(4) to if_bridge using the same ruleset.
 > 
 > >Only inbound bridged packets are passed to ipfw from bridge(4) .. once
 > >allowed in, they go out.  My reading of if_bridge(4) suggests that ipfw
 > >(etc) may also be examining outbound bridged packets, depending on the
 > >sysctls.  How have you got the sysctls mentioned in if_bridge(4) set?
 > 
 > 
 > my sysctl.conf variables:
 > 
 > net.link.bridge.ipfw=1
 > net.link.bridge.pfil_member=1
 > net.link.bridge.pfil_onlyip=1
 > net.link.bridge.pfil_bridge=0
 > net.link.bridge.ipfw_arp=1

Again, only from reading the manual (and thanks for the free course :)

     net.link.bridge.ipfw         Set to 1 to enable layer2 filtering with
                                  ipfirewall(4), set to 0 to disable it. This
                                  needs to be enabled for dummynet(4) support.
                                  When ipfw is enabled, pfil_bridge and 
                                  pfil_member will be disabled so that IPFW is
                                  not run twice; these can be re-enabled if
                                  desired.

You have reenabled both (apparently the order of setting these matter!),
so this implies running ipfw twice, like routing.  Thus, you do need to
let packets in, and then let 'em out again.

 >  > The rest of my ruleset seems to be working fine but this problem is causing me a little paranoia
 >  > about the effectiveness of the firewall.
 >  > 
 >  > Also, should I still be seeing "deny (snip) in via bridge0" messages in by logs
 >  > if I have this set "net.link.bridge.pfil_bridge: 0"?

I said 'dunno' then, but given already flying on pure documentation:

net.link.bridge.pfil_bridge=0 disables filtering on the bridge
interface, as distinct from its member interfaces.  So I guess packets
coming in via your bridge interface are being denied, as requested ..

This topic would likely be much more appropriate (and probably get
better informed responses!) in freebsd-net@ ..

Cheers, Ian




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.1070711235853.13605A-100000>