Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Nov 2004 20:21:19 +0100
From:      Pawel Malachowski <pawmal-posting@freebsd.lublin.pl>
To:        freebsd-ipfw@freebsd.org
Subject:   [PATCH] limit N connections without dropping N+1
Message-ID:  <20041107192119.GA88583@shellma.zin.lublin.pl>

Next in thread | Raw E-Mail | Index | Archive | Help

--opJtzjQTFsWo+cga
Content-Type: text/plain; charset=iso-8859-2
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

Hello,

ipfw limit option allows limiting number of states generated by a rule.
If packet belongs to a registered state, it is matched; otherwise, it is
dropped.
I believie this behaviour is too restrictive. My proposal is to:
. perform rule action on matched (belonging to states) packet;
. continue packets journey through firewall if it is unmatched.

With this, we have additional possibilities, e.g. to pass first
N connections (flows) to dummynet queue with high weight and
next (starting from N+1) connections to queue with low weight.
Previous behaviour can be emulated with additional deny rule.

Current behaviour:
  ipfw add 100 skipto 300 ip from any to any out xmit rl0 limit src-addr 10
This will allow 10 outgoing flows per source IP. Packet creating 11th
state will be dropped.

After change:
  ipfw add 100 skipto 300 ip from any to any out xmit rl0 limit src-addr 10
  ipfw add 200 deny ip from any to any out xmit fxp0
This will allow 10 outgoing flows per source IP. Packet creating 11th
state will not match rule 100, so it will be check against next rule, 200.
And it will be dropped.

However, this kind of setup is possible *only* with new behaviour:
  ipfw pipe 1 config bw 1Mbit/s   queue 20KB
  ipfw pipe 2 config bw 128Kbit/s queue 5KB
  ipfw add 100 pipe 1 ip from any to any out xmit fxp0
  ipfw add 150 skipto 300 ip from any to any out xmit fxp0 limit src-addr 10
  ipfw add 200 pipe 2 ip from any to any out xmit fxp0
(This example assumes one_pass=0.)
Pass all outgoing traffic to pipe 1, additionally, if source IP generates
more than 10 states (possible P2P or download accelerator traffic), pass
all these additional connections to pipe 2 to enforce restrictive limit.


Example from live system:
ipfw -f flush
ipfw add 65000 allow ip from any to any
ipfw add 1000 skipto 10000 ip from any to any out xmit fxp0 limit src-addr 1
ipfw add 2000 skipto 20000 ip from any to any out xmit fxp0 limit src-addr 2
ipfw add 3000 count ip from any to any out xmit fxp0

// Now run pings from 10.1.4.106 to 10.1.0.1, 10.1.2.1, 10.1.7.1 hosts,
// 4th ping -c 5 from 10.1.4.106 to some other host, it matches 3000 only.

% ipfw -d show
01000  348  29232 skipto 10000 ip from any to any out xmit fxp0 limit src-addr 1
02000  694  58296 skipto 20000 ip from any to any out xmit fxp0 limit src-addr 2
03000    5    420 count ip from any to any out xmit fxp0
65000 1308 122154 allow ip from any to any
65535   25   2076 deny ip from any to any
## Dynamic rules (5):
02000    0      0 (3s) PARENT 2 icmp 10.1.4.106 0 <-> 0.0.0.0 0
01000    0      0 (3s) PARENT 1 icmp 10.1.4.106 0 <-> 0.0.0.0 0
02000  347  29148 (5s) LIMIT icmp 10.1.4.106 0 <-> 10.1.2.1 0
01000  347  29148 (5s) LIMIT icmp 10.1.4.106 0 <-> 10.1.0.1 0
02000  345  28980 (5s) LIMIT icmp 10.1.4.106 0 <-> 10.1.7.1 0

Patch is against 5.3RC2.
Probably no man page changes needed. ;)


-- 
Paweł Małachowski

--opJtzjQTFsWo+cga
Content-Type: text/plain; charset=iso-8859-2
Content-Disposition: attachment; filename="ipfw-limit-dontdrop.patch"

--- /sys/netinet/ip_fw2.c-orig	Fri Oct 29 21:29:56 2004
+++ /sys/netinet/ip_fw2.c	Sun Nov  7 19:21:56 2004
@@ -2281,8 +2281,8 @@
 			 *   These opcodes try to install an entry in the
 			 *   state tables; if successful, we continue with
 			 *   the next opcode (match=1; break;), otherwise
-			 *   the packet *   must be dropped
-			 *   ('goto done' after setting retval);
+			 *   the packet will not match, however, it will
+			 *   travel through firewall.
 			 *
 			 * O_PROBE_STATE and O_CHECK_STATE: these opcodes
 			 *   cause a lookup of the state table, and a jump
@@ -2296,12 +2296,10 @@
 			 */
 			case O_LIMIT:
 			case O_KEEP_STATE:
-				if (install_state(f,
-				    (ipfw_insn_limit *)cmd, args)) {
-					retval = IP_FW_PORT_DENY_FLAG;
-					goto done; /* error/limit violation */
-				}
 				match = 1;
+				if (install_state(f,
+				    (ipfw_insn_limit *)cmd, args))
+					match = 0;
 				break;
 
 			case O_PROBE_STATE:

--opJtzjQTFsWo+cga--



Want to link to this message? Use this URL: <http://docs.FreeBSD.org/cgi/mid.cgi?20041107192119.GA88583>