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>
