Total bandwidth control on Ubuntu
Due to an unfortunate series of events, I went from uncapped free high-speed broadband to no internet within the span of a week. I'm now limping along with some expensive data bundles until a few week's time when I can upgrade my iBurst package and get back to large caps.
Since I am running Ubuntu, I figured I'd be able to limit my bandwidth usage quite easily, unlike on some other OS's where cloud services and background updates suck your bandwidth when you're doing nothing. Unfortunately, even on Ubuntu, background services and other unknown processes chew through data unpredictably. Once, I tethered my 3G phone to Ubuntu, only to have Ubuntu use up 63Mb of data without me having browsed any websites! So I figured I needed total control.Firewall
Typically, the solution is to use a firewall. Unfortunately, I couldn't find a way to firewall by application - allowing just HTTP traffic already gives access to most background scripts and updaters, since that is the port they all use. What I wanted was quite simple: block everything
and allow only
Firefox access to the internet. Also maybe any other app I specifically choose to allow, e.g. Skype.
On Mac OS, I'd bought an app to block all access and have a whitelist of apps I allowed, but even this was less than ideal, because often I would have to grant "python" or "java" access, which means a whole lot of apps, not just one. Also, maintaining that whitelist was a pain and often I'd have to disable the firewall to let the OS update or install apps.The magic solution
I found a solution that is simple and easy to use, although a bit of command-line use is needed: I created a group called "internet" and set up a firewall rule to block all traffic other than that initiated by a user in the "internet" group.
Now, if I just added my user to the "internet" group, then all apps I start will have internet access (including all the unwanted background services that start when I log in), so instead, I don't add myself to the group. So by default, no apps have internet access. Now I open a terminal and grant that terminal access to the "internet" group, so that any app I start from that terminal will have internet access. Total control!
This might sound complicated, but it's simple. First, create the "internet" group like so:
sudo groupadd internet
Then, save this into a script:
# Firewall apps - only allow apps run from "internet" group to run
# clear previous rules
sudo iptables -F
# accept packets for internet group
sudo iptables -A OUTPUT -p tcp -m owner --gid-owner internet -j ACCEPT
# also allow local connections
sudo iptables -A OUTPUT -p tcp -d 127.0.0.1 -j ACCEPT
sudo iptables -A OUTPUT -p tcp -d 192.168.0.1/24
# reject packets for other users
sudo iptables -A OUTPUT -p tcp -j REJECT
# open a shell with internet access
sudo -g internet -s
Once you run the above script, all access is blocked (except for already-established connections, which you may need to kill), and you get a shell with internet access. Now just launch Firefox, Skype, or any other app from this terminal and only those apps will have internet access. No more run-away bandwidth leaks.
You can use "sudo watch netstat -tnp" to see which apps have internet connections (see screenshot). It's nice to have total control.