Bug 24833

Summary: after cvsup + rebuild, ipfw "check-state" does not work
Product: Base System Reporter: steve <steve>
Component: miscAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.2-STABLE   
Hardware: Any   
OS: Any   

Description steve 2001-02-03 20:40:02 UTC
After cvsup, make buildworld/buildkernel/installkernel/installworld on
3 Feb 2001, ipfw "check-state" keyword appears to do nothing.  The relevant
lines from my firewall rules file:

	add check-state
	add deny tcp from any to any established
	add pass tcp from 10.0.0.0/8 to any setup keep-state
	add pass udp from 10.0.0.0/8 to any 53,123 keep-state
	add pass icmp from 10.0.0.0/8 to any icmptype 8 keep-state

Now the "deny tcp from any to any established" rule blocks all tcp packets,
even those associated with the "keep-state" rules.

Fix: 

Temporarily move the "deny tcp from any to any established rule" *after*
the "keep-state" rules.
How-To-Repeat: 
cvsup and rebuild, use ipfw rules similar to those above.
Comment 1 Bernd Luevelsmeyer 2001-02-03 21:30:20 UTC
I've got 4.2-Stable on a PentiumII updated just now. I found that with
these rules ('ipfw list' output):
  00100 allow tcp from any to any established
  65535 deny ip from any to any
anyone can telnet or ftp into the machine or out of it. Essentially, I
think 'established' matches packets having the SYNC flag, in addition to
those having ACK or RST.

May I ask that this bug has its "Severity" increased, because this will
break many firewalls IMO. A "allow tcp from any to any established" will
render any later tcp 'deny' rule useless.
Comment 2 Bernd Luevelsmeyer 2001-02-04 01:29:15 UTC
I'm not familiar with the FreeBSD sources so I might be wrong, but
this is how I understand it:

It's the change in /usr/src/sys/netinet/ip_fw.c from version
1.131.2.12 to 1.131.2.13, around line 1221.
 if (((f->fw_tcpf != f->fw_tcpnf) ||
    (f->fw_ipflg & IP_FW_IF_TCPEST))  &&
    !tcpflg_match(tcp, f))
was replaced by
 if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f))

The 'established' flag is in fw_ipflg. It's handled in tcpflg_match(),
but since the test for fw_ipflg is gone, tcpflg_match() doesn't get
a chance anymore to do the established-thing if fw_tcpf==fw_tcpnf ,
which (I assume) indicates TCP-flags are not used in the particular
rule.
The problem is IMHO that 'established' is a TCP property but not a
TCP flag.

Re-inserting the previous condition seems to work for me. This is a
patch against 1.131.2.13:
--- .vimbk/ip_fw.c.vimbk        Fri Feb  2 15:05:48 2001
+++ ip_fw.c     Sun Feb  4 02:07:53 2001
@@ -1222,7 +1222,9 @@

                        if (f->fw_tcpopt != f->fw_tcpnopt && !tcpopts_match(tcp, f))
                                continue;
-                       if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f))
+            if (((f->fw_tcpf != f->fw_tcpnf) ||
+                        (f->fw_ipflg & IP_FW_IF_TCPEST))  &&
+                    !tcpflg_match(tcp, f))
                                continue;
                        goto check_ports;
                    }
Comment 3 Robert Watson freebsd_committer freebsd_triage 2001-02-07 07:57:54 UTC
State Changed
From-To: open->closed


The problem is believed to be resolved as of ip_fw.c:1.131.2.14, and 
the originators of the PR have confirmed that it resolves the problems 
they have been experiencing.  An updated security advisory is due to 
be released shortly.