From owner-freebsd-net Fri Feb 15 17:16: 0 2002 Delivered-To: freebsd-net@freebsd.org Received: from ns1.infowest.com (ns1.infowest.com [204.17.177.10]) by hub.freebsd.org (Postfix) with ESMTP id 9638C37B400 for ; Fri, 15 Feb 2002 17:15:54 -0800 (PST) Received: from there (eq.net [208.186.104.163]) by ns1.infowest.com (Postfix) with SMTP id 79227214BC; Fri, 15 Feb 2002 18:15:53 -0700 (MST) Content-Type: text/plain; charset="iso-8859-1" From: "Aaron D. Gifford" To: freebsd-net@freebsd.org Subject: Re: Bug in stateful code? Date: Fri, 15 Feb 2002 18:15:52 -0700 X-Mailer: KMail [version 1.3.2] References: <20020215225647.DBAB521CE8@ns1.infowest.com> <3C6DA100.3080108@tenebras.com> In-Reply-To: <3C6DA100.3080108@tenebras.com> Cc: kudzu@tenebras.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-Id: <20020216011553.79227214BC@ns1.infowest.com> Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org On Friday 15 February 2002 05:00 pm, Michael Sierchio wrote: > Aaron D. Gifford wrote: > > When it hits check-state, while it DOES match the "X.Y.Z.23 1549<-> > > X.Y.Z.44 22" dynamic rule in principal, it FAILS to match because the > > dynamic rule is expecting to see a SYN-ACK response from the remote host > > FIRST (remember, the SYN-ACK never matched this particular dynamic rule). > > Thus this dynamic rule STILL sits, expecting SYN-ACK. > > > > Since no further rules match, if you default to deny, your ACK packet > > gets dropped/denied. > > > > Is this the behavior you are seeing? > > The packet is never dropped, it's just that -- as Crist previously > pointed out -- it matches an earlier rule, so it never changes > the state of the dynamic rule in question. It's sometimes useful to > use 'add count' rules before and after 'divert natd' to see what's > happening. > Okay, I understand now. You're saying that the last packet of the three-way TCP handshake (the SYN+ACK from the INSIDE to the OUTSIDE) is NOT dropped, but passed by the "X.Y.Z.23 1549<-> X.Y.Z.44 22" rule WITHOUT that rule being updated. That indeed is a bug. Reading the code in /usr/src/sys/netinet/ip_fw.c (on my 4.5-STABLE box), I see where the problem is. Around line 780, there is a switch()/case: statement that handles normal TCP states. Because of your ruleset, you have created a dynamic rule that only sees the INSIDE-to-OUTSIDE packets but will NEVER see the reverse packets (the other dynamic rule your original post mentions will behave normally, seeing the packets in BOTH directions). The current ip_fw.c code there, in this case will PASS the matched packet, and update the timeout using dyn_rst_lifetime because it falls through the switch() statement to the default: section. I don't know what the correct "fix" is. My gut instinct is that ifpw's default: seciton (line 798) should just reject/drop the packet (return NULL) instead of what it does today, passing the packet with a very short timeout. If there are valid states that are not yet handled, they should be added and handled. Perhaps a useful solution to the bug that might have helped warn you in your specific situation would be to detect such half-seen behavior in the default case, and log a warning, since this is likely to be a common problem with anyone using ipfw stateful rules and natd. Something like: default: if (q->state == TH_SYN | TH_ACK) /* * Both forward SYN and SYN+ACK packets have been seen, * without a reverse SYN+ACK packet in between, due to a * buggy rule set, or bogus traffic from the originating host. */ if (fw_verbose) { log(LOG_SECURITY | LOG_NOTICE, "ipfw: Invalid stateful TCP rule (from %d): Middle packet " "missing from three-way TCP handshake.", q->parent->fw_number); return NULL; /* Drop the packet as if not matched */ } If you'd seen such a warning right away, without it passing your packets, you would have known it was a ruleset problem, or else asked someone on the list about the error message in the logs. Thoughts? Aaron out. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message