Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Sep 2000 16:34:24 -0500 (CDT)
From:      missnglnk <missnglnk@sneakerz.org>
To:        Luigi Rizzo <luigi@info.iet.unipi.it>
Cc:        freebsd-ipfw@FreeBSD.ORG
Subject:   Re: Issues with ipfw(8)'s dynamic rules
Message-ID:  <Pine.BSF.4.21.0009061513420.44236-100000@sneakerz.org>
In-Reply-To: <Pine.BSF.4.21.0009050845390.39513-100000@sneakerz.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 5 Sep 2000, missnglnk wrote:

> Date: Tue, 5 Sep 2000 08:46:11 -0500 (CDT)
> From: missnglnk <missnglnk@sneakerz.org>
> To: Luigi Rizzo <luigi@info.iet.unipi.it>
> Cc: freebsd-ipfw@FreeBSD.ORG
> Subject: Re: Issues with ipfw(8)'s dynamic rules
> 
> On Tue, 5 Sep 2000, missnglnk wrote:
> 
> > Date: Tue, 5 Sep 2000 08:15:20 -0500 (CDT)
> > From: missnglnk <missnglnk@sneakerz.org>
> > To: Luigi Rizzo <luigi@info.iet.unipi.it>
> > Cc: freebsd-ipfw@FreeBSD.ORG
> > Subject: Re: Issues with ipfw(8)'s dynamic rules
> > 
> > On Mon, 4 Sep 2000, Luigi Rizzo wrote:
> > 
> > > Date: Mon, 4 Sep 2000 21:42:06 +0200 (CEST)
> > > From: Luigi Rizzo <luigi@info.iet.unipi.it>
> > > To: missnglnk <missnglnk@sneakerz.org>
> > > Cc: freebsd-ipfw@FreeBSD.ORG
> > > Subject: Re: Issues with ipfw(8)'s dynamic rules
> > > 
> > > > I found some undesirable side effects with ipfw's dynamic
> > > > rules as I was toying with it today.
> > > > 
> > > > a) Expired Dynamic Rules Aren't Really Expired
> > > >    I noticed that once a dynamic rule expires (hitting its respective
> > > >    timeout value), it's not removed from the dynamic table (unless
> > > >    the dynamic table is full), so the connection is still allowed to
> > > >    continue instead of being dropped, the only indications that an
> > > 
> > > In my code at least (and i think in the CVS tree as well) rules
> > > which hit their deadline are listed but the first time a lookup
> > > crosses through them they are really removed, so the connection is
> > > not allowed (otherwise how could you see the premature expire
> > > below!)
> > 
> > Do "ipfw show" and look at the dynamic rule output, the timeout is
> > listed there, I've had several SSH connections expired but I'm still
> > able to do things, i.e. send this message via pine.
> > 
> > > >    that are sent to the console, and the combined analyzation of
> > > >    ipfw(8) and netstat(1) output.
> > > > 
> > > >    My Solution: Remove expired UDP and ICMP dynamic rules from the
> > > >                 table, and for expired TCP connections send an RST
> > > >                 to both sides of the connection, and then remove
> > > >                 expired TCP dynamic rules from the table.
> > > 
> > > You really don't want to send RST's around from your firewall!
> > 
> > Agreed.
> > 
> > > > b) Premature Rule Expiration
> > > >    TCP connections will expire prematurely if the connection has been
> > > >    idle longer than the dynamic state ACK lifetime, but shorter than
> > > ...
> > > there is no easy solution to this, as you have no idea on what the
> > > keepalive interval is, nor if it is used at all. As someone suggested to
> > > me, the only real solution is have the firewall implement keepalives
> > > by itself, but this requires keeping track of sequence numbers
> > > (not that expensive) and sending pkts out from the firewall triggered
> > > by timeouts.
> > > 
> > > Thanks for the suggestions, but i think problem a) does not really
> > > exists (or if it does, please tell me on which version of the system
> > > you see it) and problem b) cannot be solved the way you suggest.
> > 
> > 4.0-RELEASE gives you the "invalid state" messages scrolling down the
> > screen after the connections expires, and 5.0-CURRENT increments the
> > expiration time by the value of the dynamic RST lifetime even though the
> > connection has expired, also not once have I had an expired connection
> > drop.
> > 
> > Can't problem B be solved by silently dropping the connection?
> 
> I meant problem A, not B.

Try this (sloppy, but I think you can see the point):
--- sys/netinet/ip_fw.c.orig	Wed Sep  6 00:41:12 2000
+++ sys/netinet/ip_fw.c	Wed Sep  6 12:29:12 2000
@@ -735,4 +735,3 @@
 	    break ;
-	default:
-#if 0
+	case TH_RST | (TH_RST << 8) :
 	    /*
@@ -741,7 +740,15 @@
 	     */
-	    if ( (q->state & ((TH_RST << 8)|TH_RST)) == 0)
-		printf("invalid state: 0x%x\n", q->state);
-#endif
+	    printf("invalid state: 0x%x\n", q->state);
 	    q->expire = time_second + dyn_rst_lifetime ;
 	    break ;
+	default:
+	    printf("packet should be dropped (state: 0x%x)\n", q->state);
+            old_q = q ;
+            if (prev != NULL)
+                prev->next = q = q->next ;
+            else
+                ipfw_dyn_v[i] = q = q->next ;
+            dyn_count-- ;
+            free(old_q, M_IPFW);
+	    break ;
 	}
@@ -1277,4 +1284,34 @@
 		 */
-		if (q == NULL && f->fw_flg & IP_FW_F_KEEP_S)
-		    install_state(chain);
+		if (q == NULL && f->fw_flg & IP_FW_F_KEEP_S) {
+		    switch(proto) {
+		        case IPPROTO_TCP:
+		            if (flags & TH_SYN) {
+		                DEB(printf("-- installing state for TCP packet\n"));
+		                install_state(chain);
+		            } else {
+		                DEB(printf("-- invalid TCP connection state\n"));
+		            }
+                            break;
+		        case IPPROTO_UDP:
+		            DEB(printf("-- installing state for UDP packet\n"));
+		            install_state(chain);
+                            break;
+		        case IPPROTO_ICMP:
+		            if (is_icmp_query(ip)) {
+		                DEB(printf("-- installing state for ICMP packet\n"));
+		                install_state(chain);
+		            } else {
+		                DEB(printf("-- invalid ICMP connection state\n"));
+		            }
+                            break;
+		        default:
+#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
+		            DEB(printf("-- installing state for unknown packet\n"));
+		            install_state(chain);
+#else
+		            DEB(printf("invalid unknown protocol connection state\n"));
+#endif
+                            break;
+                    }
+		}
 #endif

a) Fuzz #1 + #2"
   The default action before was to simply increment the state's
expiration time by the dynamic RST lifetime amount, I changed it to remove
the state instead.

b) Fuzz #3:
   After adding the code in fuzzes #1 and #2, I saw that a new state would
be installed if the matching rule wasn't protocol-specific (i.e. allow ip
from any to any keep-state), so I added some protocol matching code before
calling install_state().

WARNING: I consider my code very messy as only as a cheap bandaid for now,
in other words, this should not be used on production machines until
cleaned up.
--
missnglnk@sneakerz.org
http://www.sneakerz.org/~missnglnk/

> > > 	cheers
> > > 	luigi
> > > -----------------------------------+-------------------------------------
> > >   Luigi RIZZO, luigi@iet.unipi.it  . Dip. di Ing. dell'Informazione
> > >   http://www.iet.unipi.it/~luigi/  . Universita` di Pisa
> > >   TEL/FAX: +39-050-568.533/522     . via Diotisalvi 2, 56126 PISA (Italy)
> > >   Mobile   +39-347-0373137
> > > -----------------------------------+-------------------------------------
> > > 
> > --
> > missnglnk@sneakerz.org
> > http://www.sneakerz.org/~missnglnk
> > 
> > 
> > 
> > 
> > To Unsubscribe: send mail to majordomo@FreeBSD.org
> > with "unsubscribe freebsd-ipfw" in the body of the message
> > 
> 
> 
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-ipfw" in the body of the message
> 



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ipfw" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0009061513420.44236-100000>