Make sure your firewall is always running

Here’s a script I saw today for testing whether your firewall is up and running. It relies on your having logging enabled in the “Advanced” sheet of the firewall pane in Sharing Preferences. The author is Mark Hunte, a frequent poster to MacOSXhints.com [posted here with his permission].

on idle
	set myname to "ipfw_check.app" -- name you MUST give this app.
	try
		set the_checking to do shell script "ps -axc | grep -c ipfwloggerd"
	on error
		set the_checking to 0
	end try
	if the_checking is equal to 0 then
		tell application "Finder"
			activate
			display dialog "Your FireWall Appears to be TURNED OFF " & return & "Or you have not turned on Logging" & return buttons {"Open Firewall Pane", "Remind me in 5mins"} default button 1
			if the button returned of the result is "Open Firewall Pane" then
				my _change(myname)
			else
				return 300
			end if
		end tell
	else
		do shell script "killall " & quoted form of myname
	end if
end idle

on _change(myname)
	tell application "System Preferences"
		activate
		
		set current pane to pane "com.apple.preferences.sharing"
		delay 1
		reveal (first anchor of current pane whose name is "Firewall")
		do shell script "killall " & quoted form of myname
		--I could have used quit me but for som reason it would wait a while befor quiting.
	end tell
end _change

I’m going to post here what I posted in that Mac OS X Hints thread. Apologies for the cross-site cross-post.

Technically, the firewall isn’t an independent process, so you can’t directly query its “running” status. If you want to determine whether or not your firewall is “running”, all you’re really attempting to ascertain is if you’re blocking any ports. Think of it as a binary operation: either you’re wide open or you’re not (and there are ports being blocked–number is irrelevant).

There are three basic tests you need here:

  1. Is there only one ipfw entry?

  2. Is the rule number 65535?

  3. Does the rule state “allow ip from any to any”?

If all three conditions are true, you’re wide open. This is might be more solid than checking on ipfwloggerd, and perhaps more portable, as it doesn’t rely on ipfwloggerd to be running. (You never know who’s going to use your code where.)

Before we begin, it’s important to note that when you’re dealing with shell commands, even in AppleScript, you should always use /full/path/names to avoid $PATH exploits. See this post:

http://bbs.applescript.net/viewtopic.php?pid=52253#p52253

Use this as a base for a stronger script and add whatever reactions you’d like it to have upon whatever output you want it to spit out. (This is an “on run” script, so feel free to modify it to behave in an “on idle” situation to suit needs.)


on run

set firewallState to do shell script ("#!/bin/sh

echo=/bin/echo
grep=/usr/bin/grep
ipfw=/sbin/ipfw
wc=/usr/bin/wc

ruleSet=`$ipfw show`

if [ `$echo \"$ruleSet\" | $wc -l` == 1 ] && [ `$echo \"$ruleSet\" | $grep -e '^65535' &> /dev/null ; $echo $?` == 0 ] && [ `$echo \"$ruleSet\" | $grep -e 'allow ip from any to any$' &> /dev/null ; $echo $?` == 0 ]
then
	$echo \"firewall is currently allowing all traffic in and out\"
else
	$echo \"firewall is currently denying traffic\"
fi

exit") with administrator privileges

return firewallState

end run

Mikey-san’s script can also be configured this way to include a password for it:

-- Reconfigured to get a password from your keychain. See note below.
set Ss to "#!/bin/sh
echo=/bin/echo
grep=/usr/bin/grep
ipfw=/sbin/ipfw
wc=/usr/bin/wc
ruleSet=`$ipfw show`
if [ `$echo \"$ruleSet\" | $wc -l` == 1 ] && [ `$echo \"$ruleSet\" | $grep -e '^65535' &> /dev/null ; $echo $?` == 0 ] && [ `$echo \"$ruleSet\" | $grep -e 'allow ip from any to any$' &> /dev/null ; $echo $?` == 0 ]
then
	$echo \"firewall is currently allowing all traffic in and out\"
else
	$echo \"firewall is currently denying traffic\"
fi
exit" -- the shell script part

-- Note that he has carefully escaped every internal " in Ss. AppleScript will look after changing the returns from ASCII Character 13 to 10.

set firewallState to do shell script Ss password getPassw() with administrator privileges
firewallState

(*
The following handler assumes you have a password in your keychain called ASPW (could be anything you want) saved as a generic key. To do that, open your Keychain Access (in Utilities) application, choose file New, and in the sheet give it a name, enter your account name and type the password you want to use (your admin password in this case). OK. Now find the new password and double-click it. Under the attributes tab change Kind to generic key (it will be Applications). This makes for a fast search because there aren't many of them. Switch to the access control tab and select the "Allow all applications to access this item" button. Enter your admin password in the dialog that appears, and you are done. The first time you run the script, you'll have to click "Always Allow" in the dialog that appears - perhaps several times. After that, it won't ask.
*)

to getPassw()
	tell application "Keychain Scripting"
		launch
		tell current keychain to ¬
			tell (some generic key whose name is "ASPW")
				return password
			end tell
	end tell
end getPassw