I had occasion recently to try and figure out how to use the builtin firewall to prevent some “bot” from hitting the services running on a Macbook. Mac OS X comes with the FreeBSD firewall program that called IPFW. It’s a very powerful tool and gives you good abilities to manage your outbound/inbound traffic.
Just like how we normally use iptables on Linux, I will show several usage examples for reference. All these examples are in command-line mode.
Prevent a range of source IP addressed from accessing specified services.
sudo /sbin/ipfw add 02009 deny tcp from 18.104.22.168/28 to any 80 in
Here 02009 is a rule_number.
Each rule is associated with a rule_number in the range 1..65535, with the latter reserved for the default rule. Rules are checked sequentially by rule number. Multiple rules can have the same number. If a rule is entered without specifying a number, the kernel will assign one in such a way that the rule becomes the last one before the default rule.
Tcp is the protocol type, which can also be altered to ip or udp to meet your needs.
Deny multiple IP addresses in one command.
sudo ipfw -q add deny src-ip 10.0.0.0/24, 127.0.0.1/8
Drops random incoming packets with a specified probability. Here it is 5%:
sudo ipfw add prob 0.05 deny ip from any to any in
A similar effect can be achieved making use of dummynet pipes:
ipfw add pipe 10 ip from any to any ; ipfw pipe 10 config plr 0.05
Limit traffic from local clients.We can use pipes to limit bandwidth. If we want to limit traffic from local clients on 192.168.2.0/24 we can run command like this:
sudo ipfw add pipe 1 ip from 192.168.2.0/24 to any out sudo ipfw pipe 1 config bw 300Kbit/s queue 50KBytes
We use the out modifier so that the rule is not used twice. Remember in fact that ipfw rules are checked both on incoming and outgoing packets.
If we want to simulate a bidirectional link with bandwidth limitations, the correct way is as follows:
ipfw add pipe 1 ip from any to any out ipfw add pipe 2 ip from any to any in ipfw pipe 1 config bw 64Kbit/s queue 10Kbytes ipfw pipe 2 config bw 64Kbit/s queue 10Kbytes
Port forwarding with ipfw. Forward port 80 to local port 3000.
sudo ipfw add 100 fwd 127.0.0.1,3000 tcp from any to any 80 in
Another typical application of the traffic shaper is to introduce some delay in the communication. This can significantly affect applications which do a lot of RPC and where the round-trip-time of the connection often becomes a limiting factor much more than bandwidth:
ipfw add pipe 1 ip from any to any out ipfw add pipe 2 ip from any to any in ipfw pipe 1 config delay 250ms bw 1Mbit/s ipfw pipe 2 config delay 250ms bw 1Mbit/s
A more sophisticated example is limiting the outbound traffic on a net with per-host limits, rather than per-network limits:
ipfw add pipe 1 ip from 192.168.2.0/24 to any out ipfw add pipe 2 ip from any to 192.168.2.0/24 in ipfw pipe 1 config mask src-ip 0x000000ff bw 200Kbit/s queue 20Kbytes
ipfw rule management. Clear all of the rules. In a terminal window, run:
sudo /sbin/ipfw -f flush
Delete a rule with its rule_number:
sudo ipfw delete 02009
Finally, please note that this command is DEPRECATED, and it’s recommended to use pfctl instead. :p