# FILE: ipfwstate.patch # WRITTEN BY: Aaron D. Gifford - http://www.adg.us/ # PURPOSE: Patch the FreeBSD kernel's ipfw system so that it more # tightly controls bogus traffic, and warns the firewall # administrator when there's fishy TCP traffic (or there's # a buggy rule set). # REQUIRES: It is best (but not absolutely necessary) if you apply # Aaron's other ipfw patch first, the one that adds # "lifetime" capabilities to ipfw's stateful dynamic rules. # --- /usr/src/sys/netinet/ip_fw.c.orig Mon Jun 17 13:35:59 2002 +++ /usr/src/sys/netinet/ip_fw.c Mon Jun 17 13:38:03 2002 @@ -796,16 +796,35 @@ q->expire = time_second + dyn_fin_lifetime ; break ; default: -#if 0 - /* - * reset or some invalid combination, but can also - * occur if we use keep-state the wrong way. - */ - if ( (q->state & ((TH_RST << 8)|TH_RST)) == 0) - printf("invalid state: 0x%x\n", q->state); -#endif - q->expire = time_second + dyn_rst_lifetime ; - break ; + if ( (q->state & ((TH_RST << 8)|TH_RST)) != 0) { + q->expire = time_second + dyn_rst_lifetime ; + break ; + } else if (q->state == (TH_SYN | TH_ACK)) { + /* + * Both forward SYN and ACK packets have been seen, without + * a reverse SYN+ACK packet in between, because of bogus + * traffic, a buggy firewall rule set, or multiple packet + * paths (which make stateful rules useless). + */ + if (fw_verbose) { + log(LOG_SECURITY | LOG_NOTICE, + "ipfw: Dynamic TCP rule (%d) expired because of " + "missing middle packet in three-way TCP handshake.\n", + q->rule->fw_number); + } + } else { + /* + * Any other state is also invalid. + */ + if (fw_verbose) { + log(LOG_SECURITY | LOG_NOTICE, + "ipfw: Dynamic TCP rule (%d) expired because of " + "an invalid TCP state: 0x%x\n", q->rule->fw_number, + q->state); + } + } + q->expire = 0; /* Expire this invalidated dynamic rule */ + return NULL; /* And drop the offending packet */ } } else { /*