December 20, 2020
First, please don’t take this post as concrete security advice. Everyone’s situation, risk profile, and risk tolerance is different. But if you’re like me, you may not have your macOS firewall turned on right now. I’m not going to judge, especially if you’re on a trusted network behind a well configured router. You can check by going to System Preferences > Security & Privacy > Firewall.
I will suggest though that when you leave your cozy home or office network, turning on that firewall is a good idea, especially if you have anything switched on in the Sharing panel.
Figure 1: Firewall: On
Consistently remembering to do that is a chore so you may choose to leave the firewall on permanently. I don’t, because when I’m at my home office I want the Mac fully accessible from other devices on my network, and when I’m away I want things locked down as tight as I can get them.
Here’s how I have my macOS firewall switch off automatically when I’m on my home network and switch back on whenever I leave.
While connected to your home network, open Terminal and type:
system_profiler SPNetworkDataType | grep IPv4\.Router
You’ll see something that starts with:
Network Signature: IPv4.Router=192.168.0.1; ...
That 4-number IP address is probably the internal (to your network) address of your router. You might see the MAC (IPv4.RouterHardwareAddress) of your router on the same line, but let’s confirm it. Substitute the IP address from above when you type:
arp 192.168.0.1 | head -n 1 | awk '{print $4}'
You should see 6 hex numbers separated by a colon. This is your router’s MAC address and you’ll use it in the script below.
Create the following script in a location of your choice somewhere in your home folder. For me this script is called /Users/gene/bin/networkchanged
. Substitute in your router’s MAC address for the $GATEWAYMAC
string of zeroes below.
#! /bin/bash GATEWAYIP=`system_profiler SPNetworkDataType | grep -m1 IPv4\.Router | awk -F'[=;]' '{print $2}'` if [ ! -z "$GATEWAYIP" ]; then GATEWAYMAC=`arp $GATEWAYIP | head -n 1 | awk '{print $4}'` fi if [ ! -z "$GATEWAYMAC" ] && [ $GATEWAYMAC == "00:00:00:00:00:00" ]; then # Trusted network. Disable firewall. /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off else # Not on a trusted network. Enable firewall. /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on --setblockall on fi
Substitute in the location of your script and run this from the terminal:
chmod u+x /Users/gene/bin/networkchanged
Run this from the terminal:
sudo /Users/gene/bin/networkchanged
You’ll probably see the following output:
Firewall already disabled.
Now disconnect from your home network (unplug your network cable and/or turn off your Mac’s wifi) and run the script again. You should see:
Firewall is enabled. (State = 1) Firewall is set to block all non-essential incoming connections
Nice. You can also open System Preferences > Security & Privacy > Firewall and confirm that the little yellow light is on. Note that the state of this light only refreshes when you quit and relaunch System Preferences.
As root
, create a file called /Library/LaunchDaemons/com.scripts.NetworkChanged.plist
with the following contents. Substitute the full path to your networkchanged
script.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \ "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>networkchanged</string> <key>LowPriorityIO</key> <true/> <key>ProgramArguments</key> <array> <string>/Users/gene/bin/networkchanged </string> </array> <key>WatchPaths</key> <array> <string>/private/var/run/</string> </array> <key>RunAtLoad</key> <true/> </dict> </plist>
Make sure it’s owned by root:
sudo chown root:wheel /Library/LaunchDaemons/com.scripts.NetworkChanged.plist
Load it:
sudo launchctl load /Library/LaunchDaemons/com.scripts.NetworkChanged.plist
And you’re all set.
Take your computer off and bring it back onto your network and confirm that the firewall starts and stops correctly. Remember that you have to quit and re-launch System Preferences the see the effect of your script on the indicator light.