# Macros
ext_if="axe0"
prv_if="axe1"
dmz_if="axe2"
# prv_hosts -- the list of addresses of hosts on the screened LAN
prv_hosts = "{192.168.1.10, 192.168.1.15, 192.168.1.20 192.168.1.21 192.168.1.22}"
# dmz_hosts -- the list of addresses of hosts in the DMZ
dmz_hosts = "{192.168.2.21/32, 192.168.2.22/32, 192.168.2.23/32, 192.168.2.26/32, 192.168.2.27/32, 192.168.2.28/32}"
# dmz_www -- the address of the WWW server in the DMZ
dmz_www = "192.168.2.21/32"
# dmz_smtp -- the address of the SMTP server in the DMZ
dmz_smtp = "192.168.2.22/32"
# dmz_dns -- the address of the DNS server in the DMZ
dmz_dns = "192.168.2.23/32"
# Tables
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 }
table <bruteforce> persist
# all IP addresses assigned to the firewall
table <firewall> const { self }
# Options
set require-order yes
set block-policy drop
set optimization aggressive
set loginterface $ext_if
set fingerprints "/etc/pf.os"
set ruleset-optimization none
set state-policy if-bound
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 }
################ Queueing ##################################
altq on $ext_if bandwidth 984Kb hfsc queue { q_pri, q_def, q_mus, q_tor }
queue q_pri bandwidth 49% priority 7 hfsc
queue q_def bandwidth 49% priority 5 hfsc (linkshare 49%) {q_smtp,q_http,ssh_login,q_def1}
queue ssh_login bandwidth 96% priority 5 hfsc
queue q_http bandwidth 1% priority 4 hfsc
queue q_smtp bandwidth 1% priority 4 hfsc
queue q_def1 bandwidth 1% priority 3 hfsc (default)
queue q_mus bandwidth 1% qlimit 200 priority 4 hfsc
queue q_tor bandwidth 1% qlimit 25 priority 3 hfsc (upperlimit 272Kb)
################ Translation (NAT) ##################################
# Translation rules are first match
# NAT internal hosts
nat on $ext_if inet from ! $ext_if to any -> $ext_if
# redirect connections to port 80 (HTTP) to DMZ
rdr on $prv_if inet proto tcp from $prv_hosts to $ext_if port {www, https} -> $dmz_www port 80
rdr on $ext_if inet proto tcp from any to $ext_if port {www, https} -> $dmz_www port 80
# redirect connections to port 25 (SMTP) to DMZ
#rdr on $prv_if inet proto tcp from $prv_hosts to $ext_if port smtp -> $dmz_smtp port smtp
rdr on $ext_if inet proto tcp from any to $ext_if port smtp -> $dmz_smtp port smtp
#rdr pass on $ext_if proto tcp from any to $ext_if port 25 -> $dmz_smtp port 25
# redirect connections to port 53 (DNS) to DMZ
rdr on $ext_if inet proto {tcp, udp} from any to $ext_if port 53 -> $dmz_dns
# DENY rouge redirections
no rdr
################ Traffic Normalizaton ##################################
# Set ttl to 254 to limit possible mapping of hosts behind firewall.
# Also set random-id to help with the same.
match in all scrub (no-df random-id min-ttl 254 max-mss 1440 reassemble tcp)
match out all scrub (no-df random-id)
################ Filtering ##################################
# don't filter on the loopback interface
set skip on lo0
# Block spoofed packets: enable "set state-policy if-bound" above
antispoof log quick for { lo0 $dmz_if $prv_if $ext_if }
block log all
pass quick on lo0 all
block drop in quick on $ext_if from <bruteforce>
block in quick on $ext_if from <rfc1918> to any
block 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
# Block anything coming from source we have no back routes for
block in log quick from no-route to any
# Anti-fake return scans
block return-rst out on $ext_if proto tcp all
block return-rst in on $ext_if proto tcp all
block return-icmp out on $ext_if proto udp all
block return-icmp in on $ext_if proto udp all
# Block and log outgoing packets that don't have our address as source,
# they are either spoofed or something is misconfigured. NAT disabled,
# (for instance), we want to be nice and don't send out garbage.
block out log quick on $ext_if from ! $ext_if to any
# Block nmap os detection scans
block in quick proto tcp flags FUP/WEUAPRSF
block in quick proto tcp flags WEUAPRSF/WEUAPRSF
block in quick proto tcp flags SRAFU/WEUAPRSF
block in quick proto tcp flags /WEUAPRSF
block in quick proto tcp flags SR/SR
block in quick proto tcp flags SF/SF
# only allow ssh connections from the local network if it's from the
# trusted computer, 192.168.1.10. use "block return" so that a TCP RST is
# sent to close blocked connections right away. use "quick" so that this
# rule is not overridden by the "pass" rules below.
block return in quick on $prv_if proto tcp from ! 192.168.1.10 \
to $prv_if port ssh
# allow ssh connections in on the external interface as long as they're
# NOT destined for the firewall (i.e., they're destined for a machine on
# the local network). log the initial packet so that we can later tell
# who is trying to connect. use the tcp syn proxy to proxy the connection.
# the default flags "S/SA" will automatically be applied to the rule by
# PF.
#pass in log on $ext_if proto tcp to ! <firewall> \
port ssh synproxy state
#pass in on $ext_if proto tcp from any to $ext_if port ssh flags S/SA keep state (max-src-conn 1, max-src-conn-rate 3/5, overload <bruteforce> flush global)
# 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 out quick on $dmz_if from $prv_hosts to any flags S/SA
# pass all connections to the WWW host in the DMZ
pass in quick on $ext_if inet proto tcp from any to $dmz_www port {www, https} flags S/SA synproxy state
pass in quick on $ext_if inet proto tcp from any to $ext_if port {www, https} flags S/SA keep state
pass out quick on $dmz_if inet proto tcp from any to $ext_if port {www, https} flags S/SA keep state
pass out quick on $dmz_if inet proto tcp from any to any port {www, https} flags S/SA keep state
#pass all connections to the SMTP host in the DMZ
pass in log on $ext_if proto tcp from any to $dmz_smtp port smtp flags S/SA synproxy state
pass in log on $prv_if proto tcp from $prv_hosts to $dmz_smtp port smtp flags S/SA synproxy state
pass out log on $dmz_if proto tcp from any to $dmz_smtp port smtp
pass in on $dmz_if proto tcp from $dmz_smtp to any port smtp
pass out log on $ext_if proto tcp from $dmz_if to any port smtp
# pass all connections to the DNS host in the DMZ
pass in on $ext_if inet proto {tcp, udp} from any to $dmz_dns port 53 flags S/SA keep state