# # Default PF configuration file. # # This file contains the main ruleset, which gets automatically loaded # at startup. PF will not be automatically enabled, however. Instead, # each component which utilizes PF is responsible for enabling and disabling # PF via -E and -X as documented in pfctl(8). That will ensure that PF # is disabled only when the last enable reference is released. # # Care must be taken to ensure that the main ruleset does not get flushed, # as the nested anchors rely on the anchor point defined here. In addition, # to the anchors loaded by this file, some system services would dynamically # insert anchors into the main ruleset. These anchors will be added only when # the system service is used and would removed on termination of the service. # # See pf.conf(5) for syntax. # # References for modifications: # The Book of PF by Peter N.M. Hansteen, p. 21 # http://ikawnoclast.com/security/mac-os-x-pf-firewall-avoiding-known-bad-guys/ # http://support.apple.com/kb/HT5519?viewlocale=en_US&locale=en_US # http://blog.scottlowe.org/2013/05/15/using-pf-on-os-x-mountain-lion/ # http://krypted.com/mac-security/a-cheat-sheet-for-using-pf-in-os-x-lion-and-up/ # Internal interface; use the command `ifconfig -a` or: # $ ifconfig | pcregrep -M -o '^[^\t:]+:([^\n]|\n\t)*status: active' | egrep -o -m 1 '^[^\t:]+' int_if = "@INTERFACE@" # VPN network (uncomment '#vpn#' comment lines) # $vpn_net == utun0/24 when Tunnelblick creates utun0 #vpn# vpn_net = "10.8.0/24" # utun0 interface doesn't exist at boot time # Options set block-policy return set fingerprints "/etc/pf.os" set ruleset-optimization basic set skip on lo0 # Normalization # Scrub incoming packets scrub in all no-df # # com.apple anchor point # scrub-anchor "com.apple/*" # Queueing # Translation # OpenVPN Server NAT # # The Book of PF, p. 21 # Allow VPN connections to the VPN host: # http://serverfault.com/questions/555594/troubleshoot-broken-tcp-from-openvpn-client-to-server-but-ping-traceroute-work #tun_if = "utun0" #no nat on ! $tun_if from $vpn_net to ($int_if) #nat on ! $tun_if from $vpn_net to ! ($int_if) -> ($int_if) # Use a list in case Tunnelblick creates multiples utun interaces #tun_if = "{ utun0, utun1, utun2, utun3, utun4, utun5, utun6, utun7, utun8, utun9 }" #vpn# not_tun_if = "{ !utun0, !utun1, !utun2, !utun3, !utun4, !utun5, !utun6, !utun7, !utun8, !utun9 }" #vpn# no nat on $not_tun_if from $vpn_net to ($int_if) #vpn# nat on $not_tun_if from $vpn_net to ! ($int_if) -> ($int_if) # This rule must be included below BEFORE these packets are passed by other rules: # pass in quick on $tun_if reply-to $tun_if from $vpn_net to $int_if nat-anchor "com.apple/*" rdr-anchor "com.apple/*" dummynet-anchor "com.apple/*" anchor "com.apple/*" load anchor "com.apple" from "/etc/pf.anchors/com.apple" # macOS Server Adaptive Firewall # Comment out for non-macOS Server instances # anchor "com.apple.server-firewall/*" # load anchor "com.apple.server-firewall" from "/etc/pf.anchors/com.apple.server-firewall" # Filtering # Block by default block all # Debugging: #pass quick log (all, to pflog0) all #block log (all, to pflog0) all # debugging rules # $ sudo ifconfig pflog0 create # $ sudo tcpdump -n -e -ttt -i pflog0 # $ sudo ifconfig pflog0 destroy # block log (all, to pflog0) all # Allow VPN connections to the VPN host: # http://serverfault.com/questions/555594/troubleshoot-broken-tcp-from-openvpn-client-to-server-but-ping-traceroute-work # pass in quick on $tun_if reply-to $tun_if from $vpn_net to $int_if # Rule for a lot of utun interfaces in case Tunnelblick creates extras #vpn# pass in quick on utun0 reply-to utun0 from $vpn_net to $int_if #vpn# pass in quick on utun1 reply-to utun1 from $vpn_net to $int_if #vpn# pass in quick on utun2 reply-to utun2 from $vpn_net to $int_if #vpn# pass in quick on utun3 reply-to utun3 from $vpn_net to $int_if #vpn# pass in quick on utun4 reply-to utun4 from $vpn_net to $int_if #vpn# pass in quick on utun5 reply-to utun5 from $vpn_net to $int_if #vpn# pass in quick on utun6 reply-to utun6 from $vpn_net to $int_if #vpn# pass in quick on utun7 reply-to utun7 from $vpn_net to $int_if #vpn# pass in quick on utun8 reply-to utun8 from $vpn_net to $int_if #vpn# pass in quick on utun9 reply-to utun9 from $vpn_net to $int_if # Local net table const { 10/8, 172.16/12, 192.168/16 } table const { ::1, fe80::/10 } pass quick inet from to any keep state pass quick inet6 from to any keep state # Antispoof antispoof log quick for $int_if inet # Block to/from illegal destinations or sources block drop in log quick from no-route to any block drop in log quick from urpf-failed to any # This is observed on macOS #block drop in log quick on $int_if from any to 255.255.255.255 # Whitelist # Hardcoded IPs #mydomainname_com = "xxx.xxx.xxx.xxx" #table const { $mydomainname_com } #pass in quick from #pass out quick to # Block brute force attacks table persist block drop log quick from # Allow application-specific traffic over these interfaces # multicast DNS pass on $int_if proto { udp, tcp } to { 224.0.0.2, 224.0.0.18, 224.0.0.251 } port mdns pass on $int_if proto igmp to { 224.0.0.1, 224.0.0.22, 224.0.0.251 } # quick pass of Tor relay ports to avoid blocks below #tor_relay = "{ 9001, 9030 }" #pass in quick proto tcp from any to $int_if port $tor_relay #pass out quick proto tcp from $int_if port $tor_relay to any # Open Source IP blocks # Refresh with pfctl -a blockips -T load -f @PREFIX@/etc/@NAME@/blockips.conf anchor 'blockips' label "Open Source IP Blocks" load anchor 'blockips' from '@PREFIX@/etc/@NAME@/blockips.conf' # ICMP icmp_types = "echoreq" pass inet proto icmp from $int_if:network to any icmp-type $icmp_types pass inet proto icmp from any to $int_if icmp-type $icmp_types # allow out the default range for traceroute(8): # "base+nhops*nqueries-1" (33434+64*3-1) pass out on $int_if inet proto udp from any to any port 33433 >< 33626 # Allow critical system traffic pass in quick inet proto udp from port bootps to port bootpc pass out quick inet proto udp from port bootpc to port bootps # LAN services: block access, except from localnet lan_udp_services = "{ domain, net-assistant, 5001, 5900, postgresql }" lan_tcp_services = "{ domain, auth, nntp, www, \ 311, 3128, net-assistant, 5001, 5900, privoxy, postgresql, \ 8123, 8180, 8181, 9150, 9151 }" block in proto tcp from any to $int_if port $lan_tcp_services block in proto udp from any to $int_if port $lan_udp_services pass in inet proto udp from $int_if:network to $int_if port $lan_udp_services pass in inet proto tcp from $int_if:network to $int_if port $lan_tcp_services pass out proto udp from $int_if port $lan_udp_services to $int_if:network pass out proto tcp from $int_if port $lan_tcp_services to $int_if:network # Add vpn_net if running OpenVPN #vpn# pass in inet proto udp from $vpn_net to $int_if port $lan_udp_services #vpn# pass in inet proto tcp from $vpn_net to $int_if port $lan_tcp_services #vpn# pass out proto udp from $int_if port $lan_udp_services to $vpn_net #vpn# pass out proto tcp from $int_if port $lan_tcp_services to $vpn_net # Internet services internet_udp_services = "{ https, 500, openvpn, \ 1701, 4500, 5060, 5190, 5297, 5298, 5678, 16384 }" internet_tcp_services = "{ 995, 1640, 1723, 2195, \ 2196, 4190, 5218, 5223, 5190, 5220, 5222, 5298, \ 8008, 8443, 8800, 8843, 9001, 9030 }" pass in proto udp from any to $int_if port $internet_udp_services pass in proto tcp from any to $int_if port $internet_tcp_services pass out inet proto udp from $int_if to any port $internet_udp_services pass out inet proto tcp from $int_if to any port $internet_tcp_services #apns_services = "{ 2195, 2196 }" #pass in proto tcp from any port $apns_services to #pass out inet proto tcp to any port $apns_services from # ssh really restrictive pass in inet proto tcp from any to $int_if port ssh \ keep state (max-src-conn 5, max-src-conn-rate 5/2, \ overload flush global) pass out inet proto tcp from $int_if port ssh # web, mail more restrictive pass in inet proto tcp from any to $int_if \ port { smtp, https, imap, submission, imaps } \ keep state (max-src-nodes 50, max-src-conn 200, max-src-conn-rate 100/10, \ overload flush global) pass out inet proto tcp from $int_if to any \ port { smtp, imap4-ssl, imap, submission, imaps } # I2P #i2p_port = "65530" #pass in inet proto { udp, tcp } from any to $int_if port $i2p_port #pass out inet proto { udp, tcp } from $int_if port $i2p_port to any