PF is an IP firewall in that it operates on TCP/IP packets by looking at values in the network layer (IP) and transport layer (e.g. TCP) headers of each packet. Decisions about the fate of each packet are made based on matching the header values with specific rules that allow or deny the packets.
See the IPfilter package for more information. It can be found at http://coombs.anu.edu.au/~avalon/ip-filter.html
pfctl(8) pf.conf(5) pflogd(8)
net.inet.ip.forwarding=1
pf=YES
Firewalling falls into two main categories with respect to how they treat their rulesets. One method is first match wins, in which the first rule that matches a given IP packet will determine that packets fate. last match wins firewalling has quite naturally the exact opposite behavior where the last rule to match the packet will determine its fate.
% sudo pfctl -R -f /etc/pf.conf
% sudo pfctl -F r
% sudo tcpdump -n -ttt -i pflog0
% sudo tcpdump -n -ttt -r /var/log/pflog | more
Note that the rules must also appear in the following order if they appear.
These options control various protocol timeout values Examples from the manual page:
set timeout tcp.established 3600
set timeout { tcp.opening 30, tcp.closing 900 }
You can turn on statistics logging per network interface. Statistics include packet and byte counts.
set loginterface dc0
Set limits on memory usage for session state information or fragment re-assembly. Example:
set limit { states 20000, frags 20000 }
The various optimization values change how quickly sessions timeout from the state table.
set optimization aggressive
There are a number of possible ways to modify how scrub re-assembles packets. Please see the manual page for exact details.
There is some ambiguity about this behavior in the documentation. It is not clear if IP options are always blocked (whether you use 'scrub' or not) or if it is indeed use of 'scrub' that enables it.. There is also an allow-opts clause that may be used on filter rules to actually let packets with IP options through your firewall.
scrub in all
The example would turn packet scrubbing on for packets received on all interfaces.
See http://bio3d.colorado.edu/tor/sadocs/tcpip/nat.html
Two rules would be needed to cover both directions..
return-rst for TCP connections
return-icmp an ICMP UNREACHABLE by default
multiple matches mean multiple log entries.
on <intfc> e.g. on fxp0
<action> <dir> <log> <quick> <interface> <af>
.. <proto> <hosts> <flags> <icmp> <state> <misc>
proto tcp
proto { tcp, udp }
from <host> port <port> to <host> port <port>
{ <host>, <host> }
<op> may be: = != < <= > >=
<bop> may be: <> or ><
port N >< M
port N <> M
flags <a>/<b>
e.g. F or SA or FSRPAU
flags <a>/<b>
flag(s) in <a> can (and must) be turned ON:
flags <a>
flag(s) in <b> can be turned ON:
flags /<b>
icmp-type <type>
icmp-type <type> code <code>
keep-state
modulate-state
ext_if = "fxp0"
or
my_net = "10.0.0.0/24"
pass out on $ext_if from $my_net to any
pass out all pass in all
ext = "fxp0" scrub in on $ext all block in log on $ext all block return-rst in log on $ext proto tcp all block return-icmp in log on $ext proto udp all
block out log quick on $ext from ! $my_ip to any
pass out log on $ext proto tcp \
from any to any keep state
block in log quick on $ext from { \
10.0.0.0/8, \
172.16.0.0/12, \
192.168.0.0/16, \
localhost, \
0.0.0.0/32, \
255.255.255.255/32 \
} to any
pass in on $ext inet proto icmp all \
icmp-type { echorep, timex, unreach }
pass in on $ext inet proto udp from any to any \
port { = domain, = 1053 }
pass in on $ext inet proto tcp from any to any \
port { = smtp, = http, = https, = ssh }
block in quick on xl0 from 10.0.0.0/8 to any block in quick on xl0 from 172.16.0.0/12 to any block in quick on xl0 from 192.168.0.0/16 to any block in quick on xl0 from 255.255.255.255/32 to any
interface
protocol
source address
source port
destination address
destination port