On a workstation where you are the only user, you can use a very simple /etc/pf.conf: set skip on lo0 # don't filter localhost packets ext_if = "em0" # replace em0 with your external interface set block-policy drop # by default, drop packets. You can also set block-policy reject set loginterface $ext_if # log that interface block all # block all traffic by default pass in inet proto icmp icmp-type 8 code 0 # icmp packets pass in inet proto icmp icmp-type 3 code 4 # icmp needfrag (MTU) pass in inet6 proto ipv6-icmp icmp6-type {2 128} keep state pass out all # pass all outgoing traffic This will allow the necessary ICMP traffic (useful for network diagnosis) while blocking all other incoming connections. (As a general rule, the last matching rule determines the action.) I generally don't whitelist by IP addresses because I've had times where I needed to access a system from a different IP. I also avoid OS fingerprinting because, although it is available, it's not 100%25 accurate. To load the ruleset once you've edited it, run: $ doas pfctl -f /etc/pf.conf To disable the firewall (useful for diagnosing the network), run: $ doas pfctl -d To enable it again: $ doas pfctl -e For a server, you will want to, at a minimum, allow incoming ssh packets: set skip on lo0 # don't filter localhost packets ext_if = "em0" # my external interface is em0 set block-policy drop # by default, drop packets. You can also set block-policy reject set loginterface $ext_if # log that interface pass in proto tcp from 192.168.1.1 to port ssh pass in inet proto icmp icmp-type 8 code 0 # icmp packets pass in inet proto icmp icmp-type 3 code 4 # icmp needfrag (MTU) pass in inet6 proto ipv6-icmp icmp6-type {2 128} keep state pass out all # pass all outgoing traffic Replace 192.168.1.1 with your IP. As a general rule, your servers should also accept incoming http and https connections. This is necessary for running a web server and also for acquiring a properly signed SSL certificate. Here is the /etc/pf.conf: set skip on lo0 # don't filter localhost packets ext_if = "em0" # my external interface is em0 set block-policy drop # by default, drop packets. You can also set block-policy reject set loginterface $ext_if # log that interface pass in proto tcp from 192.168.1.1 to port ssh pass in inet proto icmp icmp-type 8 code 0 # icmp packets pass in inet proto icmp icmp-type 3 code 4 # icmp needfrag (MTU) pass in inet6 proto ipv6-icmp icmp6-type {2 128} keep state pass in proto tcp to port {http https} pass out all # pass all outgoing traffic To see how many packets are arriving: $ doas pfctl -f /etc/pf.conf This will empty the existing state tables for pf. Then, run $ doas pfctl -sr -v This will show you how many packets are arriving. Since you emptied the state tables, if you now see 1000s of packets coming in, those packets came in the last few seconds, indicating that you are certainly under attack.