From owner-freebsd-questions@freebsd.org Thu Aug 20 15:15:12 2015 Return-Path: Delivered-To: freebsd-questions@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D31CD9BFC31 for ; Thu, 20 Aug 2015 15:15:12 +0000 (UTC) (envelope-from smithi@nimnet.asn.au) Received: from sola.nimnet.asn.au (paqi.nimnet.asn.au [115.70.110.159]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D415BA3B for ; Thu, 20 Aug 2015 15:15:07 +0000 (UTC) (envelope-from smithi@nimnet.asn.au) Received: from localhost (localhost [127.0.0.1]) by sola.nimnet.asn.au (8.14.2/8.14.2) with ESMTP id t7KFEwAi062694; Fri, 21 Aug 2015 01:14:58 +1000 (EST) (envelope-from smithi@nimnet.asn.au) Date: Fri, 21 Aug 2015 01:14:58 +1000 (EST) From: Ian Smith To: andreas scherrer cc: freebsd-questions@freebsd.org, freeb-ipfw@freebsd.org Subject: Re: ipfw's "via" rule option/match pattern In-Reply-To: Message-ID: <20150821001041.H8515@sola.nimnet.asn.au> References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 Aug 2015 15:15:12 -0000 In freebsd-questions Digest, Vol 585, Issue 3, Message: 9 On Wed, 19 Aug 2015 00:41:35 +0200 andreas scherrer 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