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% 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