Deny access to a port from localhost on OSX

I want to test a fallback strategy for my memcached driver (in case port is protected by firewall). How can I deny access to a specific port, on 127.0.0.1?


Example for Mac OS X 10.6 (Snow Leopard)

to deny connections to localhost, port SSH (= 22, read from /etc/services):

sudo ipfw add deny tcp from any to localhost ssh

You can use pfctl.

OS X 10.7 "Lion" and later use the OpenBSD PF (Packet Filter). A pseudo-device called /dev/pf allows user space tools to configure the packet filter. The command pfctl provides most of the functionality.

To filter port 1234 on the loopback interface you can use a rule like this:

block drop quick on lo0 proto tcp from any to any port = 1234

This rules blocks all inbound/outbound traffic on lo0 for port 1234 (quick means in this context that if this rule matches, no further rule should be applied).

The command to load the rule in PF is:

(sudo pfctl -sr 2>/dev/null; echo "block drop quick on lo0 proto tcp from any to any port = 1234") | sudo pfctl -nf -

Command pfctl -sr 2>/dev/null lists all current rules (and sends the pretty annoying error message No ALTQ support in kernel ALTQ related functions disabled to /dev/null). The echo adds the rule above to the output, which is piped to pfctl. Option -n means don't apply, just check.

If there's no error message (apart from the aforementioned No ALTQ support message and the warning pfctl: Use of -f option, could result in flushing of rules present in the main ruleset added by the system at startup), you can apply the rule:

(sudo pfctl -sr 2>/dev/null; echo "block drop quick on lo0 proto tcp from any to any port = 1234") | sudo pfctl -f - 2>/dev/null

This command differs from the previous one in that I removed -n. Note that you may have to add option -e to enable the packet filter (thanks for your comment, casey): (sudo pfctl -sr 2>/dev/null; echo "block drop quick on lo0 proto tcp from any to any port = 1234") | sudo pfctl -e -f - 2>/dev/null

You can list now the rules to check it has been added properly:

sudo pfctl -sr 2>/dev/null
(...)
block drop quick on lo0 proto tcp from any to any port = 1234

When you're done you can delete the rule:

  1. either loading the original set of rules:

    sudo pfctl -f /etc/pf.conf 
    
  2. or removing the rule in a similar manner the rule was added:

    (sudo pfctl -sr 2>/dev/null | fgrep -v "block drop quick on lo0 proto tcp from any to any port = 1234") | sudo pfctl -f -
    

(I've tested the whole procedure on OS X 10.8.2 "Mountain Lion" and worked flawlessly.)

You can find more information in this excellent introduction: http://nomoa.com/bsd/gateway/pf/valid/pfctl.html.

ipfw is still included in OS X 10.7 and 10.8 but is deprecated:

IPFW(8)                   BSD System Manager's Manual                  IPFW(8)

NAME
     ipfw -- IP firewall and traffic shaper control program (DEPRECATED)

SYNOPSIS
(...)

DESCRIPTION
     Note that use of this utility is DEPRECATED. Please use pfctl(8) instead.