After reading all that I could find on pf, including "The Book of PF" and "Building Firewalls with OpenBSD and PF" I have a made my first pf.conf, but I am hoping those with experience with PF would look over my configuration and give me any tips or pointers.
Code:
# Macros
# ext_if -- the interface to the outside world
ext_if="axe0"
# prv_if -- the interface to the private hosts
prv_if="axe1"
localnet = $prv_if:network
# dmz_if -- the interface to the DMZ
dmz_if="axe2"
# prv_hosts -- the list of addresses of hosts on the screened LAN
prv_hosts = "{ 192.168.1.10, 192.168.1.11 }"
# dmz_hosts -- the list of addresses of hosts in the DMZ
dmz_hosts = "{ 192.168.2.2/32, 192.168.2.3/32, 192.168.2.4 }"
# dmz_www -- the address of the WWW server in the DMZ
dmz_www = "192.168.2.2/32"
# dmz_smtp -- the address of the SMTP server in the DMZ
dmz_smtp = "192.168.2.3/32"
# dmz_dns -- the address of the DNS server in the DMZ
dmz_dns = "192.168.2.4/32"
# known ports
www_ports = "{ http, https }"
mail_ports = "{ smtp, pop3, imap, imaps, pop3s }"
# Tables
# Non-routable addresses
table <rfc1918> const { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, 0.0.0.0/8, 240.0.0.0/4 }
# Options
set skip on lo
set reassemble yes
set require-order yes
set block-policy drop
set loginterface $ext_if
set state-policy if-bound
set fingerprints "/etc/pf.os"
set ruleset-optimization none
# Timeout options
set optimization aggressive
set timeout { frag 30, tcp.established 120 }
set timeout { tcp.first 30, tcp.closing 30, tcp.closed 30, tcp.finwait 30 }
set timeout { udp.first 30, udp.single 30, udp.multiple 30 }
set timeout { other.first 30, other.single 30, other.multiple 30 }
# Block spoofed packets: enable "set state-policy if-bound" above
antispoof log quick for { lo0 $dmz_if $prv_if ($ext_if) }
# Block non routable addresses
block drop in quick on $ext_if from <rfc1918> to any
block drop out quick on $ext_if from any to <rfc1918>
block in quick on $ext_if inet from any to 255.255.255.255
block in log quick on $ext_if inet from urpf-failed to any
block in log quick on $ext_if inet from no-route to any
# Normalize packets
# 4.7 change to scrub
match in all scrub (no-df random-id min-ttl 5 max-mss 1440 reassemble tcp)
match out on $ext_if scrub (no-df random-id)
# Translate packets
# nat for the private hosts
match out on egress from $prv_hosts to any nat-to egress
# nat for the DMZ hosts
match out on egress from $dmz_hosts to any nat-to egress
# redirect connections to port 80 (HTTP) to DMZ
match in on egress inet proto tcp from any to any port $www_ports rdr-to $dmz_www
# redirect connections to port 25 (SMTP) to DMZ
match in on egress inet proto tcp from any to any port 25 rdr-to $dmz_smtp
# redirect connections to port 53 (DNS) to DMZ
match in on egress inet proto { tcp, udp } from any to any port 53 rdr-to $dmz_dns
# Filter packets
# block all incoming connections sent from the outside
# log all blocked packets
#block all
block log on $ext_if
block return log on $prv_if
block return log on $dmz_if
# pass all connections originating from the firewall
pass out quick on $ext_if inet \
from ($ext_if) to any flags S/SA modulate state
# pass all connections originating from the screened LAN
pass in quick on $prv_if from $prv_hosts to any flags S/SA
# pass all connections originating from the DMZ
pass in quick on $dmz_if from $dmz_hosts to any flags S/SA
# pass all connections to the WWW host in the DMZ
pass in on $ext_if proto { tcp, udp } from any to $dmz_www \
port $www_ports flags S/SA synproxy state
# pass all connections to the SMTP host in the DMZ
pass in on $ext_if proto { tcp, udp } from any to $dmz_smtp \
port $mail_ports flags S/SA synproxy state
# pass all connections to the DNS host in the DMZ
pass in on $ext_if proto { tcp, udp } from any to $dmz_dns \
port 53 flags S/SA keep state