Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Aug 2015 01:14:58 +1000 (EST)
From:      Ian Smith <smithi@nimnet.asn.au>
To:        andreas scherrer <ascherrer@gmail.com>
Cc:        freebsd-questions@freebsd.org, freeb-ipfw@freebsd.org
Subject:   Re: ipfw's "via" rule option/match pattern
Message-ID:  <20150821001041.H8515@sola.nimnet.asn.au>
In-Reply-To: <mailman.100.1439985602.54249.freebsd-questions@freebsd.org>
References:  <mailman.100.1439985602.54249.freebsd-questions@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
In freebsd-questions Digest, Vol 585, Issue 3, Message: 9
On Wed, 19 Aug 2015 00:41:35 +0200 andreas scherrer <ascherrer@gmail.com> wrote:
 > Dear all
 > 
 > I am struggling to understand ifpw's "via" rule option. I am on FreeBSD 
 > 10.1-release-p16
 > 
 > I have read ipfw(8) [1] many times by now but I still find it confusing:
 > 
 > "The via keyword causes the interface to always be checked. If recv or 
 > xmit is used instead of via, then only the receive or transmit interface 
 > (respectively) is checked."
 > 
 > What does "the interface is checked" mean in this context? And what is a 
 > common use case for the "via" rule option as opposed to recv/xmit? "in 
 > via" seems to be the same as "in recv" anyway (because "in xmit" is 
 > invalid) if I read "via" as "recv or xmit"...

The interface is checked to match the one (or ones) specified.  in recv 
is indeed the same as in via, because as received from ip(6)_input, only 
the receive interface is known .. the transmit interface is only known 
on outgoing packets after routing has chosen it, before ip(6)_output (or 
ether_demux and ether_output_frame respectively if matching at layer 2 - 
see ipfw(8) PACKET FLOW)

 > I have also read (and I believe understood) [2], [3] and [4]. But it 
 > somehow contradicts what I see on my system. Or at least I think so.

Yes, I believe you're right .. and [2] and [4] were written by me.  I 
had a look at the code tonight (duh!) and suspect I've been at least 
partially wrong all the years I've been posting about this :(
 
 > Mainly they all state that something like
 > 
 > ... out via ifX
 > 
 > matches packets that are *going through* a box (read: are forwarded) if 
 > they came in on interface ifX and are leaving the box via ifY.

These packets need not be being forwarded .. they might originate on 
this box, and then they have no recieve interface, ie never came 'in'.

 > That would be because the packet's receive interface is checked when it 
 > leaves the box and because it entered the box on ifX the rule matches 
 > (even if the packet leaves the box on ifY).
 > 
 > [4]: "Again, 'out via $wan_if' is ambiguous, and includes packets 
 > _received_ on $wan_if and now being transmitted to the inside"
 > 
 > When I run a quick test, sending one ICMP echo request from 
 > 192.168.32.10 to 192.168.38.17 (two devices communicating via the box 
 > that has the "count" rules listed below configured), I get the following 
 > result:

A good set of tests for all combinations.  Something else I saw recently 
made me doubt that my own understanding of this was correct, and your 
tests seem to confirm that I've been misadvising people for, oh, the 
best part of 10 years .. here's the code, which I've checked hasn't 
functionally changed at all since 2012, and little from 2002 with 
Luigi's first ip_fw2.c (tabs lost):

                case O_RECV:
                        match = iface_match(m->m_pkthdr.rcvif,
                            (ipfw_insn_if *)cmd, chain, &tablearg);
                        break;

                case O_XMIT:
                        match = iface_match(oif, (ipfw_insn_if *)cmd,
                            chain, &tablearg);
                        break;

                case O_VIA:
                        match = iface_match(oif ? oif :
                            m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd,
                            chain, &tablearg);
                        break;

iface_match() (qv) does the test vs iface name or IP address, returning 
1 on a match, but begins by returning 0 if the passed interface is NULL.  
In the case of O_VIA, if the outside iface is specified then that iface 
(only) is tested; the rcvif is only checked if there's NO out iface.

This directly contradicts what I've been telling myself and others for 
years :( I guess what's amazing is that nobody who'd know better ever 
pulled me up on such statements, increasing confidence in wrongness :)

 > -----
 > When 192.168.38.17 does not answer the ping:
 > 00350     2     168 count icmp from 192.168.32.10 to 192.168.38.17 recv re0.32
 > 00350     0       0 count icmp from 192.168.38.17 to 192.168.32.10 recv re0.38
 > 00351     1      84 count icmp from 192.168.32.10 to 192.168.38.17 in recv re0.32
 > 00351     0       0 count icmp from 192.168.38.17 to 192.168.32.10 in recv re0.38
 > 00352     1      84 count icmp from 192.168.32.10 to 192.168.38.17 out recv re0.32
 > 00352     0       0 count icmp from 192.168.38.17 to 192.168.32.10 out recv re0.38
 > 00355     1      84 count icmp from 192.168.32.10 to 192.168.38.17 via re0.32
 > 00355     0       0 count icmp from 192.168.38.17 to 192.168.32.10 via re0.38
 > 00356     1      84 count icmp from 192.168.32.10 to 192.168.38.17 in via re0.32
 > 00356     0       0 count icmp from 192.168.38.17 to 192.168.32.10 in via re0.38
 > 00357     0       0 count icmp from 192.168.32.10 to 192.168.38.17 out via re0.32
 > 00357     0       0 count icmp from 192.168.38.17 to 192.168.32.10 out via re0.38
 > 00358     1      84 count icmp from 192.168.32.10 to 192.168.38.17 out recv re0.32 xmit re0.38
 > 00358     0       0 count icmp from 192.168.38.17 to 192.168.32.10 out recv re0.38 xmit re0.32
 > 
 > When 192.168.38.17 does answer the ping:
 > 00350     2     168 count icmp from 192.168.32.10 to 192.168.38.17 recv re0.32
 > 00350     2     168 count icmp from 192.168.38.17 to 192.168.32.10 recv re0.38
 > 00351     1      84 count icmp from 192.168.32.10 to 192.168.38.17 in recv re0.32
 > 00351     1      84 count icmp from 192.168.38.17 to 192.168.32.10 in recv re0.38
 > 00352     1      84 count icmp from 192.168.32.10 to 192.168.38.17 out recv re0.32
 > 00352     1      84 count icmp from 192.168.38.17 to 192.168.32.10 out recv re0.38
 > 00355     1      84 count icmp from 192.168.32.10 to 192.168.38.17 via re0.32
 > 00355     1      84 count icmp from 192.168.38.17 to 192.168.32.10 via re0.38
 > 00356     1      84 count icmp from 192.168.32.10 to 192.168.38.17 in via re0.32
 > 00356     1      84 count icmp from 192.168.38.17 to 192.168.32.10 in via re0.38
 > 00357     0       0 count icmp from 192.168.32.10 to 192.168.38.17 out via re0.32
 > 00357     0       0 count icmp from 192.168.38.17 to 192.168.32.10 out via re0.38
 > 00358     1      84 count icmp from 192.168.32.10 to 192.168.38.17 out recv re0.32 xmit re0.38
 > 00358     1      84 count icmp from 192.168.38.17 to 192.168.32.10 out recv re0.38 xmit re0.32
 > -----
 > 
 > According to the statement in [4] I would expect rule 357 to match...

Yes; [4] is clearly wrong in this respect.  'out via' does NOT check the 
receive interface if the transmit interface is known.

 > Can anyone shed some light on that topic for me? I have a feeling that 
 > my understanding that "via" is "recv or xmit" is not correct.
 > 
 > Thanks in advance
 > andreas
 > 
 > [1] https://www.freebsd.org/cgi/man.cgi?query=ipfw(8)
 > [2] 
 > https://lists.freebsd.org/pipermail/freebsd-questions/2005-July/094739.html
 > [3] 
 > https://groups.google.com/forum/#!topic/comp.unix.bsd.freebsd.misc/AkDSKlUmVok
 > [4] 
 > https://lists.freebsd.org/pipermail/freebsd-questions/2011-June/231271.html

Posting this also to freebsd-ipfw@ for comments, clarifications, or 
plain old getting beaten up.  Perhaps ipfw(8) could benefit other users 
by clarifying in particular this 'out via' behaviour.

Please cc me on responses in -questions@, I'm subscribed to the digest.

cheers, Ian



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20150821001041.H8515>