From owner-freebsd-net Fri Feb 15 14:57: 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 3EA8737B417 for ; Fri, 15 Feb 2002 14:56:49 -0800 (PST) Received: from there (eq.net [208.186.104.163]) by ns1.infowest.com (Postfix) with SMTP id DBAB521CE8; Fri, 15 Feb 2002 15:56:47 -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 15:56:46 -0700 X-Mailer: KMail [version 1.3.2] Cc: kudzu@tenebras.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-Id: <20020215225647.DBAB521CE8@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 I use stateful rules and natd together without any trouble. You just have to think through VERY carefully exactly what is happening to each and every packet during it's journey and write your rules accordingly. Let's look at your example ruleset, Michael: Michael Sierchio (kudzu@tenebras.com) wrote: >$on = external net = X.Y.Z/24 >$in = internal net = A.B.C/24 (192.168.1.0/24) > >the external IP is X.Y.Z.23 >the internal IP is A.B.C.1 > >firewall rules: > >[some static rules...] > >$fw add divert natd ip from any to any via $external_interface > >$fw add check-state > >$fw add allow tcp from $in to any setup keep-state >$fw add allow udp from $in to any keep-state > >$fw add allow tcp from $on to any setup keep-state >$fw add allow udp from $on to any keep-state > >An ssh connection from A.B.C.4 to X.Y.Z.44 causes the following dynamic rules >to appear: > >02400 15 3197 (T 16, slot 760) <-> tcp, X.Y.Z.23 1549<-> X.Y.Z.44 22 >02200 45 9151 (T 296, slot 913) <-> tcp, A.B.C.4 1549<-> X.Y.Z.44 22 After carefully reading your above rules, I can assure you that you're NOT seeing a bug at all, and what you see is what I expect SHOULD be happening. Let's follow a SYN, SYN-ACK, ACK three-way TCP handshake through your ruleset: Your SYN packet from INSIDE to OUTSIDE first traverses your ruleset IN VIA your internal interface. It MATCHES your rule: "$fw add allow tcp from $in to any setup keep-state" This adds the dynamic rule you see as "A.B.C.4 1549<-> X.Y.Z.44 22". Next, your packet goes through the list again, this time OUT VIA your external interface. It matches your NAT divert rule, the source address of the SYN packet gets changed from A.B.C.4 to A.B.C.1. This now modified packet does NOT MATCH the check-state because the source address differs. So this same SYN packet now matches this rule: "$fw add allow tcp from $on to any setup keep-state" That's the other dynamic rule you see as "X.Y.Z.23 1549<-> X.Y.Z.44 22" Now let's trace the SYN-ACK packet from X.Y.Z.44 port 22 back to your inside machine. It enters IPFW as a packet IN VIA your external interface, so this packet immediately matches your NAT divert rule and is rewritten with a DESTINATION address of "A.B.C.D 1549". This reply packet will NEVER hit your check-state, and that's why the dynamic rule "X.Y.Z.23 1549<-> X.Y.Z.44 22" stays in the SYN state until it times out. Continuing on, the now translated SYN/ACK now hits the check-state and MATCHES the dynamic rule "A.B.C.4 1549<-> X.Y.Z.44 22" and that rule's timeout is updated just fine. Now you your inside source sends an ACK packet back to complete the 3-way handshake. This ACK enters as an IN VIA internal interface packet. It doesn't match the NAT divert, but it DOES match the "A.B.C.4 1549<-> X.Y.Z.44 22" check-state rule, and updates the dynamic rule's timeout. Next it enters your ruleset OUT VIA your external interface, hits the NAT divert, and gets translated. It then continues through the rules. 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? If anyone is interested, I'd be happy to post my ipfw rules I use at home. I have a single Internet visible IP and a few hosts translated sitting behind it on a broadband connection. Aaron out. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message