[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: optimizing pf firewall

On Thu, Oct 06, 2005 at 03:48:17PM -0400, Dave wrote:
> pf.conf
> # pf.conf
> # for use on gateway box
> # Required order: options, normalization, queueing, translation, filtering.
> # Macros and tables may be defined and used anywhere.
> # Note that translation rules are first match while filter rules are last 
> match.
> # define the two network interfaces
> ext_if = "rl0"
> int_if = "rl1"
> # define some address macros
> lan_server = ""
> # define services
> int_to_lan_services = "{ ssh, smtp, www, pop3, https, pop3s, 1194, 1723, 
> 8000 }"
> lan_to_int_services = "{ ftp-data, ftp, ssh, smtp, 43, domain, http, pop3, 
> nntp, imap, https, imaps, pop3s, 1790, 1791, 1792, 1793, 1794, 1795, 2401, 
> 4000, 4662, 4711,
> 5000, 5001, 5190, cvsup, 6112, 6667, 8000, 8021, 8080, 8505, 8880, 9102 }"
> lan_to_fw_services = "{ ssh }"
> fw_to_lan_services = "{ ssh, 9101, 9102, 9103 }"
> nameservers = "{ xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxx }"
> isp_dhcp_server = ""
Wherever you have multiple addresses listed, it is my preference to use
tables.  Not only are they faster, they'll also allow you to add to them
on the fly, control them from a single separate file, etc.  Though, for
3 addresses, you may not even care.
> # options
> set optimization normal
> set block-policy drop
> set require-order yes
> set fingerprints "/etc/pf.os"
> # normalize packets to prevent fragmentation attacks
> scrub on $ext_if all random-id reassemble tcp
> scrub on $int_if inet no-df
Any particular reason you are not 'fragment reassemble' here?
> # Thwart nmap scans
> block in log quick on $ext_if proto tcp all flags FUP/FUP
IMO, a good ruleset should never need something like this.  Unless you
are in a very weird environment, your default policy should *always* be
drop/return and log.  If that were the case, provided you didn't
explicitly allow traffic that is supposedly generated from nmap, your
default policy would catch it and log it.
The rest of the rules, which I've deleted for brevity, look reasonable.
The only suggestion I'd have is to, at the very top of your rules
section, clearly define your default policies.  In your case, you've got
default block rules scattered amongst allow rules which makes getting
the overall picture difficult.
Also, the following rule will likely come back to haunt you:
> # allow UDP requests to port 53 from lan clients to enter LAN
> # in order to perform dns queries on the firewall (keep state on this 
> connection)
> pass in quick on $int_if inet proto udp from $int_if:network to $int_if 
> port 53 keep state
See the archives for the past week as to why this is bad.  In short, if
the query is too large (>512 bytes) (hint: nslookup pool.ntp.org), the
RFC states that the client must(?) then try the same query using TCP.
If you don't allow 53/tcp, you ntp connections might mysteriously stop
Just some general style hints, too.  These are just my personal
preferences but you may find them useful:
   * If you find yourself typing the same string more than, say,
     3 times, its probably worthy of a macro IMO.  Ones that
     I commonly use include:
         TCP_STATE="flags S/SA modulate state"
         UDP_STATE="keep state"
         PING="icmp-type 8 code 0" 
   * If you find yourself routinely typing things like $int_if:network,
     I usually also make those a macro.  i.e.:
As far as performance optimization goes, I'm not sure there is much you
can do.  Some say that a good ordering can help with this, but
probably is only worthwhile if you've got tons of rules.  Even then, the
pain of having, say, your "allow" rules before your "default block"
rules, while it may make a difference performance wise (I'm not saying
it does, but others may say so...), is probably going to bring you
a world of hurt as far as maintenence and correctness goes.
Hope this helps...