Date: Tue, 10 Dec 2002 12:40:02 +0300 (MSK) From: Oleg Koreshkov <okoreshkov@salut.ru> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/46159: ipfw dynamic rules lifetime feature Message-ID: <200212100940.gBA9e254017726@bazamot.salut.ru>
next in thread | raw e-mail | index | archive | help
>Number: 46159
>Category: kern
>Synopsis: ipfw dynamic rules lifetime feature
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Tue Dec 10 01:50:01 PST 2002
>Closed-Date:
>Last-Modified:
>Originator: Oleg Koreshkov
>Release: FreeBSD 4.7-RELEASE i386
>Organization:
A LOT OF...
>Environment:
System: FreeBSD xxxx.xxx.xx 4.7-RELEASE-p2 FreeBSD 4.7-RELEASE-p2 #8:
Thu Nov 14 18:48:42 MSK 2002 root@xxx.xxx.xx:/usr/obj/usr/src/sys/XXXXXXX i386
>Description:
When you use stateful filtering (with ipfw) it sometimes useful
to have different default lifetime for dynamic rules according
to rule body (not only for protocol). For example, on very busy
web server it's advisable to keep 'net.inet.ip.fw.dyn_ack_lifetime'
moderately short, while allow other types of tcp sessions
(smtp,ftp,ssh etc...) exist without any limitations. Another example
is allow udp/icmp packets that are outgoing from our iface have a
long dynamic rule lifetime, but for packets comes from other hosts -
short one... (because, for example, we can answer for ICMP query
quite quickly, but we don't know how fast is remote host...)
Kernel part of ipfw extended by adding extra field 'dyn_lifetime' in
ip_fw structure. Userland utility ``ipfw'' extended by adding rule
option ``lifetime <NNN>''. This option may be used standalone or
with ``keep-state'' / ``limit'' rules.
For TCP packets it option replaces lifetime for sessions in established
state (if no ``lifetime'' option apeared, then default
is net.inet.ip.fw.dyn_ack_lifetime).
For UDP packets is replaces 'net.inet.ip.fw.dyn_udp_lifetime'
For ICMP and other packets is replaces 'net.inet.ip.fw.dyn_short_lifetime'
So, while we have default lifetime for TCP sessions in established state
(kept in kern sysctl 'net.inet.ip.fw.dyn_ack_lifetime'), we may want
to explicitly define it for other sessions:
# ipfw add 1000 pass tcp from me to any setup lifetime 7200
this example mean, that dynamic rules created from this rule will
have ``dyn_ack_lifetime'' equal to 7200 seconds (2 hours).
>How-To-Repeat:
use patch below:
cd /usr/src
patch < ipfw.lifetime.patch
rebuild and install your kernel (and/or) ipfw kernel module...
rebuild ipfw and libalias (and all that statically use this library)
>Fix:
ipfw.lifetime.patch:
====================================================================================
--- sys/netinet/ip_fw.h 1.47.2.11 2002/07/09
+++ sys/netinet/ip_fw.h
@@ -159,6 +159,7 @@
#define DYN_DST_PORT 0x8
u_short conn_limit; /* # of connections for limit rule */
+ u_int32_t dyn_lifetime; /* lifetime for dynamic rule */
};
#define fw_divert_port fw_un.fu_divert_port
--- sys/netinet/ip_fw.c 1.131.2.35 2002/07/29
+++ sys/netinet/ip_fw.c
@@ -783,12 +783,12 @@
break ;
case TH_SYN | (TH_SYN << 8) :
/* move to established */
- q->expire = time_second + dyn_ack_lifetime ;
+ q->expire = time_second + (q->rule->dyn_lifetime?q->rule->dyn_lifetime:dyn_ack_lifetime) ;
break ;
case TH_SYN | (TH_SYN << 8) | TH_FIN :
case TH_SYN | (TH_SYN << 8) | (TH_FIN << 8) :
/* one side tries to close */
- q->expire = time_second + dyn_ack_lifetime ;
+ q->expire = time_second + (q->rule->dyn_lifetime?q->rule->dyn_lifetime:dyn_ack_lifetime) ;
break ;
case TH_SYN | (TH_SYN << 8) | TH_FIN | (TH_FIN << 8) :
/* both sides closed */
@@ -807,10 +807,10 @@
break ;
}
} else if (pkt->proto == IPPROTO_UDP) {
- q->expire = time_second + dyn_udp_lifetime ;
+ q->expire = time_second + (q->rule->dyn_lifetime?q->rule->dyn_lifetime:dyn_udp_lifetime) ;
} else {
/* other protocols */
- q->expire = time_second + dyn_short_lifetime ;
+ q->expire = time_second + (q->rule->dyn_lifetime?q->rule->dyn_lifetime:dyn_short_lifetime) ;
}
if (match_direction)
*match_direction = dir ;
@@ -2083,6 +2083,7 @@
ip_fw_default_rule = LIST_FIRST(&ip_fw_chain_head) ;
printf("IP packet filtering initialized, "
+ "lifetime feature enabled, "
#ifdef IPDIVERT
"divert enabled, "
#else
--- sbin/ipfw/ipfw.c 1.80.2.24 2002/09/26
+++ sbin/ipfw/ipfw.c
@@ -402,6 +402,8 @@
printf(" %d", chain->conn_limit);
break ;
}
+ if(chain->dyn_lifetime)
+ printf(" lifetime %d",chain->dyn_lifetime);
}
/* Direction */
if (chain->fw_flg & IP_FW_BRIDGED)
@@ -890,6 +892,7 @@
" tcpoptions [!]{mss|window|sack|ts|cc}, ...\n"
" icmptypes {type[, type]}...\n"
" keep-state [method]\n"
+" lifetime <number>\n"
" pipeconfig:\n"
" {bw|bandwidth} <number>{bit/s|Kbit/s|Mbit/s|Bytes/s|KBytes/s|MBytes/s}\n"
" {bw|bandwidth} interface_name\n"
@@ -1958,6 +1961,16 @@
rule.dyn_type = type;
av++; ac--;
}
+ } else if (!strncmp(*av, "lifetime", strlen(*av))) {
+ u_int32_t dyn_lifetime;
+ rule.fw_flg |= IP_FW_F_KEEP_S;
+
+ av++; ac--;
+ if (ac > 0 && (dyn_lifetime = atoi(*av)) != 0) {
+ rule.dyn_lifetime = dyn_lifetime;
+ av++; ac--;
+ } else errx(EX_USAGE, "``lifetime'' needs"
+ " dynamic rule lifetime (seconds)");
} else if (!strncmp(*av, "bridged", strlen(*av))) {
rule.fw_flg |= IP_FW_BRIDGED;
av++; ac--;
====================================================================================
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200212100940.gBA9e254017726>
