Date: Tue, 3 May 2005 14:28:12 -0700 From: "David Schwartz" <davids@webmaster.com> To: "Freebsd-Ipfw@Freebsd. Org" <freebsd-ipfw@freebsd.org> Subject: Option to sanely handle dynamic rule overflow Message-ID: <MDEHLPKNGKAHNMBLJOLKOECGDJAB.davids@webmaster.com>
next in thread | raw e-mail | index | archive | help
I have a bunch of FreeBSD machines that act as firewalls. We use dynamic rules for accounting but not filtering. One problem we have is that a denial of service attack is possible by creating millions of dynamic firewall rules. This causes ipfw to drop packets. I've created a patch to make a sysctl option to cause FreeBSD to offer another option in handling packets that try to create a dynamic rule when one cannot be created. With this option selected, the rule fails to match if it cannot create a dynamic rule, allowing the packet to be handled in any way desired simply by following the rule with another rule. Below is a diff. Comments are greatly appreciated. David Schwartz - --- orig/ip_fw2.c 2005-05-03 14:02:43.987438426 -0700 +++ new/ip_fw2.c 2005-05-03 14:20:09.105853002 -0700 @@ -211,8 +211,9 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, ve */ static ipfw_dyn_rule **ipfw_dyn_v = NULL; static u_int32_t dyn_buckets = 256; /* must be power of 2 */ static u_int32_t curr_dyn_buckets = 256; /* must be power of 2 */ +static u_int32_t drop_dyn_full = 1; /* drop packets if rule table full */ static struct mtx ipfw_dyn_mtx; /* mutex guarding dynamic rules */ #define IPFW_DYN_LOCK_INIT() \ mtx_init(&ipfw_dyn_mtx, "IPFW dynamic rules", NULL, MTX_DEF) @@ -271,8 +272,10 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dy SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_short_lifetime, CTLFLAG_RW, &dyn_short_lifetime, 0, "Lifetime of dyn. rules for other situations"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive, CTLFLAG_RW, &dyn_keepalive, 0, "Enable keepalives for dyn. rules"); +SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, drop_dyn_full, CTLFLAG_RW, + &drop_dyn_full, 0, "Drop if too many dyn. rules"); #endif /* SYSCTL_NODE */ @@ -1128,8 +1131,9 @@ install_state(struct ip_fw *rule, ipfw_i last_log = time_second; printf("ipfw: install_state: Too many dynamic rules\n"); } IPFW_DYN_UNLOCK(); + if(drop_dyn_full) return 2; /* do not match */ return 1; /* cannot install, notify caller */ } switch (cmd->o.opcode) { @@ -2296,14 +2300,17 @@ check_body: * effectively NOPs. */ case O_LIMIT: case O_KEEP_STATE: - if (install_state(f, - (ipfw_insn_limit *)cmd, args)) { + retval = install_state(f, + (ipfw_insn_limit *)cmd, args); + if(retval == 1) { retval = IP_FW_PORT_DENY_FLAG; goto done; /* error/limit violation */ } - match = 1; + if(retval == 2) match = 0; + else match = 1; + retval = 0; break; case O_PROBE_STATE: case O_CHECK_STATE:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?MDEHLPKNGKAHNMBLJOLKOECGDJAB.davids>