From mikescott@clara.net  Sun Jul 29 01:38:08 2001
Return-Path: <mikescott@clara.net>
Received: from mta01-svc.ntlworld.com (mta01-svc.ntlworld.com [62.253.162.41])
	by hub.freebsd.org (Postfix) with ESMTP id 2BCFC37B403
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 29 Jul 2001 01:38:08 -0700 (PDT)
	(envelope-from mikescott@clara.net)
Received: from data.scotts ([213.104.75.148]) by mta01-svc.ntlworld.com
          (InterMail vM.4.01.03.00 201-229-121) with ESMTP
          id <20010729083806.MSER15984.mta01-svc.ntlworld.com@data.scotts>
          for <FreeBSD-gnats-submit@freebsd.org>;
          Sun, 29 Jul 2001 09:38:06 +0100
Received: (from root@localhost)
	by data.scotts (8.11.3/8.11.3) id f6T8IaU01684;
	Sun, 29 Jul 2001 09:18:36 +0100 (BST)
Message-Id: <200107290818.f6T8IaU01684@data.scotts>
Date: Sun, 29 Jul 2001 09:18:36 +0100 (BST)
From: mikescott@clara.net
Reply-To: mikescott@clara.net
To: FreeBSD-gnats-submit@freebsd.org
Cc: mikescott@clara.net
Subject: IPFW dynamic rules and NATD interaction has logical design flaw
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         29294
>Category:       kern
>Synopsis:       IPFW dynamic rules and NATD interaction has logical design flaw
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jul 29 01:40:01 PDT 2001
>Closed-Date:    Fri Aug 17 13:35:09 PDT 2001
>Last-Modified:  Fri Aug 17 13:39:07 PDT 2001
>Originator:     Mike Scott
>Release:        FreeBSD 4.3-RELEASE i386
>Organization:
(self)
>Environment:
System: FreeBSD data.scotts 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Thu Jul 19 15:20:22 BST 2001 mike@data.scotts:/usr/src/sys/compile/DATA i386

	486dx2/66 (!), os as above, with standard ipfw, natd, libraries.
	
>Description:
	There seems to be a logical error in the way natd is handled in
	conjunction with the ipfw firewall rules.  I've asked on the
	questions and hackers lists about this, but there's been little
	response - one person said my config file was wrong, another vaguely
	remembered a problem of this sort.
	(1) ipfw rules are handled top down, stop on first match.
	(2) therefore the NAT diversion must be the first item in the list,
	or it may never be reached.
	(3) keep-state and check-state must therefore both follow the NAT
	diversion. (So no trickery allowed having before-nat and after-nat
	state checks)
	(4) keep-state and check-state must work on the same set of addresses,
	either both internal, or both external.
	(5) the list of firewall rules is traversed in the same order for
	incoming and outgoing packets
	(6) therefore all rules for incoming packets are applied to *local*
	addresses, all rules for outgoing are applied to *external* addresses.
	(7) keep-state and check-state are normally applied to packets flowing
	in opposite directions.
	(8) Therefore, they are applied inconsistently to incoming and
	outgoing addresses (keep-state may save an internal address, but
	check-state will be applied to an external address, and vice versa)

	
>How-To-Repeat:
	I assume that any ipfw config of the form
	$fwcmd add divert natd all from any to any via tun0
	...
	$fwcmd add check-state
	$fwcmd add deny log tcp from any to any established
	$fwcmd add allow log tcp from any to any out via tun0 keep-state

	will exhibit the wrong behaviour.  'ipfw show' will show the
	dynamic rule(s) with the wrong addresses in
>Fix:
	Assuming I'm right, the "call" to natd doesn't belong in the fw rules.
	It should always occur just after packets are read in, just before
	they're written out to the network.
	
	Workaround is not to use dynamic rules.

>Release-Note:
>Audit-Trail:

From: "David Hedley" <david@inty.net>
To: <freebsd-gnats-submit@FreeBSD.org>, <mikescott@clara.net>
Cc:  
Subject: Re: kern/29294: IPFW dynamic rules and NATD interaction has logical design flaw
Date: Mon, 6 Aug 2001 16:14:36 +0100

 For this to work, you need to split your firewall rules between incoming and
 outgoing packets and divert them to natd at different times.
 
 i.e.
 
 add 1 skipto 30000 ip from any to any out
 # All packets at this point are now inbound
 # Map incoming external IPs to internal
 add 100 divert natd ip from any to any via tun0
 # Allow any packets that are part of an ongoing connection
 add 200 check-state
 add 300 deny log ip from any to any
 
 # Outgoing packets are processed here
 # Add in dynamic rule using non-NAT addresses
 add 30000 skipto 30100 ip from any to any via tun0 keep-state
 # Do NAT
 add 30100 divert natd ip from any to any via tun0
 add 30200 allow ip from any to any
 
 From this, both keep-state and check-state will work on internal (i.e.
 before-NAT) addresses.
 
 Hope this helps,
 
 David
 --
 Dr David Hedley, R&D Director,
 Intelligent Network Technology Ltd, Bristol, UK
 http://www.inty.net/
 
 
 --
 Information in this electronic mail message is confidential
 and may be legally privileged. It is intended solely for
 the addressee. Access to this message by anyone else is
 unauthorised. If you are not the intended recipient any 
 use, disclosure, copying or distribution of this message is
 prohibited and may be unlawful. When addressed to our
 customers, any information contained in this message is
 subject to INT Ltd Terms & Conditions.
 --
 
 This email has been virus scanned using Sophos Anti-Virus by intY (www.inty.net)
 

From: mikescott@clara.net
To: <freebsd-gnats-submit@FreeBSD.org>, <mikescott@clara.net>,
	"David Hedley" <david@inty.net>
Cc:  
Subject: Re: kern/29294: IPFW dynamic rules and NATD interaction has logical design flaw
Date: Tue, 7 Aug 2001 16:20:38 +0100

 On 6 Aug 2001, at 16:14, David Hedley wrote:
 > For this to work, you need to split your firewall rules between incoming and
 > outgoing packets and divert them to natd at different times.
 > 
 > i.e.
 > 
 > add 1 skipto 30000 ip from any to any out
 > # All packets at this point are now inbound
 > # Map incoming external IPs to internal
 > add 100 divert natd ip from any to any via tun0
 > # Allow any packets that are part of an ongoing connection
 > add 200 check-state
 > add 300 deny log ip from any to any
 > 
 > # Outgoing packets are processed here
 > # Add in dynamic rule using non-NAT addresses
 > add 30000 skipto 30100 ip from any to any via tun0 keep-state
 > # Do NAT
 > add 30100 divert natd ip from any to any via tun0
 > add 30200 allow ip from any to any
 > 
 > >From this, both keep-state and check-state will work on internal (i.e.
 > before-NAT) addresses.
 > 
 > Hope this helps,
 > 
 > David
 
 Ah, I see. Thanks for that.  Amazing how you can't see the wood sometimes.
 
 However, even though there is a workable solution, I'd still contend 
 the basic design is logically flawed -- it's the embedding of the nat 
 diversion into the firewall rules that requires that the rules be so 
 split: I'm no OS design expert, but I'm still prepared to stick my 
 neck out and say the nat should occur immediately data is 
 transferred to/from the device, in which case the firewall rules deal 
 only with one set of addresses and are much simpler.  I *think* this 
 is what happens with ipf, to which (in desperation :-) ) I've already 
 switched -- certainly the equivalent rules for ipf are much simpler 
 and seem to work as expected. (As an aside, I wonder why fbsd 
 offers two different firewalls?  ipf seems to offer a superset of ipfw's 
 facilities, claims to be portable, and if my experience is anything to 
 go by, is easier to set up: why keep ipfw?)
 
 Anyway, as this would seem to be a "feature" rather than a "fault", 
 may I suggest to anyone involved in the documentation that a 
 working example might be useful in future please!
 
 Thanks again, anyway!
 
 --
 various incoming sites blocked because of spam:
 see www.mikescott.clara.net for a list
 mikescott@clara.net           Mike Scott 
 aka mikeascott@ntlworld.com   Harlow Essex England

From: "Crist J. Clark" <cristjc@earthlink.net>
To: mikescott@clara.net
Cc: freebsd-bugs@FreeBSD.org
Subject: Re: kern/29294: IPFW dynamic rules and NATD interaction has logical design flaw
Date: Thu, 16 Aug 2001 09:47:57 -0700

 On Tue, Aug 07, 2001 at 08:30:02AM -0700, mikescott@clara.net wrote:
 >  On 6 Aug 2001, at 16:14, David Hedley wrote:
 >  > For this to work, you need to split your firewall rules between incoming and
 >  > outgoing packets and divert them to natd at different times.
 
 No, there is a much easier way.
 
   $fwcmd add divert natd all from any to any via ${natd_interface}
   $fwcmd add check-state
   $fwcmd add pass ip from ${oip} to any out via ${oif} keep-state
   $fwcmd add pass ip from ${net} to any in  via ${iif} keep-state
 
 Just create dynamic rules on packets going _in_ the internal
 interface(s). We now get two dynamic rules for each "connection," one
 using the translated source one using the private net address.
 
 >  However, even though there is a workable solution, I'd still contend 
 >  the basic design is logically flawed -- it's the embedding of the nat 
 >  diversion into the firewall rules that requires that the rules be so 
 >  split: I'm no OS design expert, but I'm still prepared to stick my 
 >  neck out and say the nat should occur immediately data is 
 >  transferred to/from the device, in which case the firewall rules deal 
 >  only with one set of addresses and are much simpler.
 
 This would require NAT to take place in the kernel which is against
 one of the fundamental design assumptions of natd(8). natd(8) works
 the way it does for good reasons. However, it is not perfect, there
 are both pros and cons to the design.
 
 >  I *think* this 
 >  is what happens with ipf, to which (in desperation :-) )
 
 Yes. ipf(8) and ipnat(8) live in the kernel. This design also has pros
 and cons.
 
 >  I've already 
 >  switched -- certainly the equivalent rules for ipf are much simpler 
 >  and seem to work as expected. (As an aside, I wonder why fbsd 
 >  offers two different firewalls?  ipf seems to offer a superset of ipfw's 
 >  facilities, claims to be portable, and if my experience is anything to 
 >  go by, is easier to set up: why keep ipfw?)
 
 ipfw(8) is the native firewall. ipf(8) is externally maintained.
 
 I think the only real bug that might be here is that the default
 rc.firewall does not actually work with natd(8) and that is not what
 the original PR is about. Unless someone objects, I am going to close
 this PR later today. If someone feels the need to, a PR about
 rc.firewall can be submitted separately.
 -- 
 Crist J. Clark                           cjclark@alum.mit.edu
State-Changed-From-To: open->closed 
State-Changed-By: cjc 
State-Changed-When: Fri Aug 17 13:35:09 PDT 2001 
State-Changed-Why:  
The issue can be solved by writing your firewall rules in the correct 
fashion. Thie "problem" is a design choice, not a bug. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=29294 
>Unformatted:
