Recently I started pushing a repository to GitHub only to find out it was a couple of GB in size. Due to my ISPs network connection being made of soiled tissue paper, dead earwigs and lost hope, it quickly saturated it. This interrupted watching Breaking Bad on Netflix. Clearly something had to be done.
Enter ipfw.
ipfw is more generally thought of as a utility for managing firewall
rules on OS X, but it’s also great for shaping traffic. Doing that is a
simple two step process: create an ipfw pipe for a data flow and then
configure how big that pipe is.
First, create a pipe which matches a flow of data. A pipe is a
combination of source address, destination address and optional matching
patterns. In my case I wanted to affect outgoing traffic to port 22
which is used by ssh, the program git generally talks to servers
with:
$ sudo ipfw add pipe 1 ip from any to any out dst-port 22
I’ve been a bit lazy here by using any for the IP address fields. I
know that only my connection to github will be using dst-port 22. The
from IP address and to IP address may be written as a specifc IP, or
a range of IPs using CIDR notation, instead of the any wildcard.
I’ve specifically set the rule to only match out going traffic. If
you want to control the flow of data in both directions, you would
generally create an in pipe and an out pipe separately
Note that I’ve named this pipe 1. This number is used to uniquely identify the pipe when carrying out other operations on it. If you create more than one pipe, be sure to use unique numbers for each one.
Next, we have to configure the pipe to control the data flow:
$ sudo ipfw pipe 1 config bw 75KBytes/s
The bw setting ensures that data passing through pipe 1 is
transferring at most 75 KBytes per second. You can set this to whatever
value is suitable for your connection.
If you want, you can check what connections are being affected:
$ sudo ipfw pipe list
00001: 600.000 Kbit/s 0 ms 50 sl. 1 queues (1 buckets) droptail
mask: 0x00 0x00000000/0x0000 -> 0x00000000/0x0000
BKT Prot ___Source IP/port____ ____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp
0 tcp 192.168.0.100/61291 207.97.227.239/22 685 991700 31 43792 0
Finally, don’t forget to remove the pipe when you no longer need to limit the data transfer rate:
$ sudo ipfw pipe delete 1
There are many other options in ipfw for shaping traffic, including
commands for dropping a certain percentage of packets (great for testing
game networking code), and you can limit the bandwidth to very small
rates which is handy for seeing how slow connections experience websites
you create. Check out the
man page
for more details.
