Skip site navigation (1)Skip section navigation (2)
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>