ipfw's "via" rule option/match pattern
andreas scherrer
ascherrer at gmail.com
Mon Aug 24 21:29:24 UTC 2015
> In freebsd-questions Digest, Vol 585, Issue 3, Message: 9
> On Wed, 19 Aug 2015 00:41:35 +0200 andreas scherrer <ascherrer at gmail.com> wrote:
<snip>
> > 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.
Thank you for your effort! I finally understand what I am doing here!
Awesome!
To be honest I was looking for the code you pasted but was not able to
find it. Now I know where to look.
In summary I think it would be reasonable to advise people to *not* use
"via" in combination with "in" or "out".
"in via $if" => "in recv $if"
"out via $if" => "out xmit $if"
Unless there can be outgoing packets without an xmit interface; but I
don't see what those would be good for.
Still looking for a use case for "via" (there must be a reason it
exists, right?) "via" seems to make more sense when used *without*
"in"/"out".
"via $if" matches packets that are either incoming on $if or outgoing on
$if. The most prominent use case that comes to my mind for that would be
NAT (hiding an RFC 1918 network):
nat X ip4 from any to any via $if
Assuming the above is correct and that I wanted to tackle the issue of
rewriting the ipfw handbook section: how would I do that (i.e. how to
submit a new version)?
Best regards
andreas
More information about the freebsd-ipfw
mailing list