From owner-freebsd-ipfw@FreeBSD.ORG Mon Sep 19 13:07:19 2005 Return-Path: X-Original-To: freebsd-ipfw@FreeBSD.org Delivered-To: freebsd-ipfw@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5983316A41F for ; Mon, 19 Sep 2005 13:07:19 +0000 (GMT) (envelope-from tataz@tataz.chchile.org) Received: from smtp3-g19.free.fr (smtp3-g19.free.fr [212.27.42.29]) by mx1.FreeBSD.org (Postfix) with ESMTP id CA1EB43D45 for ; Mon, 19 Sep 2005 13:07:18 +0000 (GMT) (envelope-from tataz@tataz.chchile.org) Received: from tatooine.tataz.chchile.org (vol75-8-82-233-239-98.fbx.proxad.net [82.233.239.98]) by smtp3-g19.free.fr (Postfix) with ESMTP id 63E0124AB2; Mon, 19 Sep 2005 15:07:17 +0200 (CEST) Received: by tatooine.tataz.chchile.org (Postfix, from userid 1000) id 51969405D; Mon, 19 Sep 2005 15:07:18 +0200 (CEST) Date: Mon, 19 Sep 2005 15:07:18 +0200 From: Jeremie Le Hen To: Martin Message-ID: <20050919130718.GO51142@obiwan.tataz.chchile.org> References: <20050917111817.GG51142@obiwan.tataz.chchile.org> <200509172042.j8HKgoEX013028@bernina.office> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200509172042.j8HKgoEX013028@bernina.office> User-Agent: Mutt/1.5.9i Cc: freebsd-ipfw@FreeBSD.org Subject: Re: in via or in recv X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Sep 2005 13:07:19 -0000 Hi Martin, > >This rule will apply on the outgoing path (because of "xmit") and will > >let through all packets that arrived on fxp0 and then leave through sis0. > > Yep, but the rule is only executed on the outgoing phase because at > the incoming phase, the xmit interfaces is unknown and as such, > the rule does not match. > > FreeBSD does have an IPFW option for single pass or regular handling > of the packets. Single pass means: Only once through the firewall rules, > done at arrival of the packet. > > The regular handling is to call the firewall rules for each packet when the > packet enters the computer and once when the packet is send out. > The words "in" and "out" in the Firewall rules are intended to give the rule > designer the opportunity to let a rule work on incoming or outgoing packets. > > When a packet enters the PC, the outgoing interface is not known yet, so > the following rules do the same: > > ipfw add allow ip from any to any in recv fxp0 > ipfw add allow ip from any to any in via fxp0 Until there, I agree. > The following two rules do NOT (in general) behave the same: > ipfw add allow ip from any to any out recv fxp0 > ipfw add allow ip from any to any out via fxp0 > > The second rule will also match packets coming in through (read "via") fxp0. This is what I read numerous times on the archives indeed. But I checked the code myself : http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/netinet/ip_fw2.c?annotate=1.111 Here is a snap from line 2480 : % case O_RECV: % match = iface_match(m->m_pkthdr.rcvif, % (ipfw_insn_if *)cmd); % break; % % case O_XMIT: % match = iface_match(oif, (ipfw_insn_if *)cmd); % break; % % case O_VIA: % match = iface_match(oif ? oif : % m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd); % break; What I understand for the "via" keyword is that when the output interface is known, then it is matched against it, and nothing more. The two rules you have used above are _not_ equivalent. In the first case we will match on the outgoing path, whatever the output interface is, but when the input one was fxp0. In the second rule, the "out" (== "not in") keyword make the rule apply only on the outgoing path [1]. Therefore `oif' will be defined and the output interface will be checked, whereas in the first rule this was the input interface. [1] "in" is implemented as : % case O_IN: /* "out" is "not in" */ % match = (oif == NULL); % break; > Things get more complicated when the packet is "created" in the PC itself. Still reading the implementation, I would say that packets generated on the machine itself will have a NULL input interface, thus the iface_match() function will never match (first statement in the function). For what I understand, I would say that if you want to only match packet generated locally, you should use something like this (although it's quite tricky and does not perform very well due to the use of strings function) : % ipfw add allow all from any to any out not recv * "recv *" will match every input interface, except when it's NULL. Please, correct me if I'm wrong. -- Jeremie Le Hen < jeremie at le-hen dot org >< ttz at chchile dot org >