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: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041107192119.GA88583>