Date: Fri, 7 Jan 2000 16:31:00 -0800 (PST) From: "Rodney W. Grimes" <freebsd@gndrsh.dnsmgr.net> To: luigi@info.iet.unipi.it (Luigi Rizzo) Cc: patrick@mindstep.com (Patrick Bihan-Faou), logix@foobar.franken.de (Harold Gutch), freebsd-current@FreeBSD.ORG, nate@mt.sri.com (Nate Williams) Subject: Re: ipfw optimizations Message-ID: <200001080031.QAA13581@gndrsh.dnsmgr.net> In-Reply-To: <200001072340.AAA06578@info.iet.unipi.it> from Luigi Rizzo at "Jan 8, 2000 00:40:53 am"
next in thread | previous in thread | raw e-mail | index | archive | help
> > No, this is completly reasonable now that I understand what it is your
> > proposing. Even the memory footprint is minimal if pointers to the
> > actual rules is all we store in the per interface list, my largest set
> > duplicated over 8 interfaces would only be 3200 rules. Stored as
>
> I'd be curious to know what your 400-rule set looks like, what is
> the longest search path through that ruleset, and whether that
> ruleset could be made more efficient to run by implementing some
> kind of switch() statement (eg. for selecting based on interfaces),
> or hash tables (e.g. you want to allow/deny to a list of random
> addresses...).
If you search the archives you'll find a function I wrote in /bin/sh
called clnsrv is what creates 90% of the rules. Ahh.. hech.. here...
# clnsrv(action, proto, sport, dport, clients, servers)
clnsrv() {
action=$1; shift
proto=$1; shift
sport=$1; shift
dport=$1; shift
clients=$1; shift
servers=$1; shift
if [ X"${proto}" = X"tcp" ]; then
setup="setup"
base=10000
else
setup=""
base=40000
fi
if [ X"${dport}" = X"" ]; then
ruleoffset=${sport}
else
ruleoffset=${dport}
fi
if [ ${ruleoffset} -gt 1899 ]; then
ruleoffset=1900
fi
rule=`expr ${base} + \( ${ruleoffset} \* 10 \)`
for cln in ${clients} ; do
for srv in ${servers} ; do
${fadd} ${rule} ${action} ${proto} \
from ${cln} ${sport} to ${srv} ${dport} ${setup}
done
done
rule=`expr ${rule} + 9`
${fadd} ${rule} ${CLASS} log ${proto} from any ${sport} to any ${dport}
}
Then this is called like so:
clnsrv "allow " tcp 20 "" "${tcp_ftpdata_c}" "${tcp_ftpdata_s}"
clnsrv "allow " tcp "" 21 "${tcp_ftp_c}" "${tcp_ftp_s}"
clnsrv "allow " tcp "" 22 "${tcp_ssh_c}" "${tcp_ssh_s}"
clnsrv "allow " tcp "" 23 "${tcp_telnet_c}" "${tcp_telnet_s}"
clnsrv "allow " tcp "" 25 "${tcp_smtp_c}" "${tcp_smtp_s}"
clnsrv "allow " tcp "" 43 "${tcp_nicname_c}" "${tcp_nicname_s}"
clnsrv "allow " tcp "" 53 "${tcp_domain_c}" "${tcp_domain_s}"
clnsrv "allow " tcp "" 79 "${tcp_finger_c}" "${tcp_finger_s}"
clnsrv "allow " tcp "" 80 "${tcp_http_c}" "${tcp_http_s}"
clnsrv "allow " tcp "" 110 "${tcp_pop3_c}" "${tcp_pop3_s}"
clnsrv "allow " tcp "" 111 "${tcp_sunrpc_c}" "${tcp_sunrpc_s}"
clnsrv "allow " tcp "" 113 "${tcp_ident_c}" "${tcp_ident_s}"
... on and on up to the 1024 and then a few splattered after that.
Note that those variables ``tcp_ftp_c'' are often long lists of IP
prefixes, and tcp_ftp_s is a single IP or ``any'', dependent on where
this firewall is in the network topology, so these calls can quickly
build into fairly long ipfw lists. Often the _c and _s will be lists,
causing the double nested loop to product a few not so meaningful rules,
but that has been fairly rare, bgp being the big exception :-).
Also this same routine is called again for a whole pile of udp ports.
The single largest optimization would probably be a dispatch based on
source or destination port, the latter being more prevelent.
I can't easily send out the actual IP firewall list, it may expose
what ever router I grabbed it off of to an attack :-)
--
Rod Grimes - KD7CAX @ CN85sl - (RWG25) rgrimes@gndrsh.dnsmgr.net
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200001080031.QAA13581>
