Updated: November 7, 2015
Per-application, outbound firewall control has always been a Windows domain. Users would seek ways to restrict their programs for making unsolicited calls home to the mothership, leaking info and whatnot. Possibly with some good reason, and for most part, they could very easily do this. Still can.
In Linux, the situation is trickier. If you hit the Intertubes searching for a solution that offers this same level of control and granularity, you will mostly find a bunch of questions and partial answers. The thing, the iptables firewall module, while quite powerful and handy, is not really designed to be an application monitor. But let's say you really want this functionality. Is there anything you can do? Follow me.
All right, so if you know your way around, then you will have asked the right question, and received many answers, all of which give you an incomplete picture. For good reason, because a network traffic filter residing in the kernel cannot easily or effectively monitor user-space applications. Moreover, how do you really allow or deny traffic? Do you base it on the binary process name, the path, the md5sum? Any other criteria? Do you monitor all protocols? Do you monitor specific ports? And what are you trying to achieve?
But then, you may also have come across an interesting little program called Leopard Flower (lpfw), whatever that means, and this is a personal firewall, with a per-application control and GUI. Sounds exactly like what we need, but given the title of my article, you may as well have guessed this guide isn't really about any spotted cats and fancy topiary. Indeed, testing lpfw does not yield satisfactory results, plus I lost all traffic when using the tool. So something else then.
g++ -g -fpermissive -std=c++11 -Wfatal-errors -c sha256/sha256.c
g++ -g -fpermissive -std=c++11 -Wfatal-errors -c base64.cpp
g++ -g -fpermissive -std=c++11 -Wfatal-errors -c conntrack.c
g++ -g -fpermissive -std=c++11 -Wfatal-errors -c testmain.cpp
Daemon tcp port:46334
gui/gui.py: 1: gui/gui.py: import: not found
from: can't read /var/mail/PyQt4.QtGui
gui/gui.py: 3: gui/gui.py: import: not found
from: can't read /var/mail/PyQt4.QtCore
from: can't read /var/mail/PyQt4.QtNetwork
from: can't read /var/mail/multiprocessing
from: can't read /var/mail/base64
gui/gui.py: 8: gui/gui.py: import: not found
gui/gui.py: 9: gui/gui.py: import: not found
gui/gui.py: 10: gui/gui.py: import: not found
from: can't read /var/mail/PyQt4
gui/gui.py: 14: gui/gui.py: Syntax error: "(" unexpected
I am not sure if this is a pun or not, because douane stands for customs, i.e. border control, and that's an applicable name for a firewall. Anyhow, this program is a new project that aims to accomplish just that.
The instructions for setting up Douane are quite tricky. You will first need to satisfy a whole bunch of dependencies. After that, you will have to manually clone and configure three different Github repos. Then, you will have to separately configure the kernel module, the daemon, the logging service, and the GUI that lets you actually intercept applications and control them. Last but not the least, to be able to run the service, you will have to manually create a systemd service script, because the installation does not provide one.
In fact, there are many little problems and bugs with the documentation, as well as the compiled code. Apart from the obvious GTK incompatibility, binary paths on the disk do not quite match the wiki, and the service startup is utterly broken. But let's solve this piece by piece.
Try to follow the instructions available online. They should work. The notable problems happen a bit later, so I will go into more details for that. The initial setup is relatively straightforward if long and complicated. The developer could have easily packaged everything into a single script. Tested in Xubuntu Vivid, so some of the commands here might not behave as nicely in Fedora or openSUSE or alike. You will forgive me that.
sudo apt-get install build-essential dkms libboost-filesystem-dev libboost-regex-dev libboost-signals-dev policykit-1 libdbus-c++-dev libdbus-1-dev liblog4cxx10-dev libssl-dev libboost-signals-dev libdbus-c++-dev libdbus-1-dev liblog4cxx10-dev libgtkmm-3.0-dev python3 python3-gi policykit-1 python3-dbus
Running module version sanity check.
- Original module
- No original module exists within this kernel
- Installing to /lib/modules/3.19.0-15-generic/updates/dkms/
DKMS: install completed.
Loading Douane Linux kernel module...
sudo make install
test -d /opt/douane || mkdir -p /opt/douane
test -d /etc/init.d/ || mkdir -p /etc/init.d/
test -d /etc/dbus-1/system.d/ || mkdir -p /etc/dbus-1/system.d/
install -m 0500 douaned /opt/douane
install -m 0755 init.d/douane /etc/init.d/
install -m 0644 system.d/org.zedroot.Douane.conf /etc/dbus-1/system.d/
Now, if you launch douane-configurator, the GUI piece, you will not be able to start the GUI service, because there is no service script:
[....] Starting douane (via systemctl): douane.serviceFailed to start douane.service: Unit douane.service
failed to load: No such file or directory.
To resolve the issue, you will need to create a file named douane.service under /lib/systemd/system. This is the location for all the system scripts for the ugly new monstrosity called systemd.
ExecStart=/usr/local/douane/douaned -l /var/log/douane.log -D
Optionally, you may use a slightly different declaration:
But this also requires the dkms.service script, which does not exist on Ubuntu, and it also reveals another problem with this firewall implementation, as the developer seems to be an Arch Linux guy. Alternatively, you can manually run the tool, and then relaunch the GUI component. If you struggle, you can always search for the douane and douaned binary on your system.
Now, for some reason, you could see these issues:
Installing Douane Linux kernel module version 0.8.2...
make: dkms: Command not found
Makefile:77: recipe for target 'dkms' failed
make: *** [dkms] Error 127
No package 'liblog4cxx' found
Package dbus-c++-1 was not found in the pkg-config search path.
Perhaps you should add the directory containing `dbus-c++-1.pc'
to the PKG_CONFIG_PATH environment variable
No package 'dbus-c++-1' found
In file included from freedesktop/desktop_file.cpp:1:0:
freedesktop/desktop_file.h:4:28: fatal error: log4cxx/logger.h: No such file or directory
Makefile:36: recipe for target 'freedesktop/desktop_file.o' failed
make: *** [freedesktop/desktop_file.o] Error 1
You are probably missing some of the build essential tools necessary for the task. You should verify that you have installed all of the needed packages and dependencies, and then try again.
Now, the tool in action. The GUI is simple and straightforward. Whenever you launch a new program, Douane will intercept it, and ask you to allow or deny. There's no per-protocol or per-port control. It's based on binaries and their full path, without any advanced logic or checking. Remember, the idea is to help you gain some of that Windows-like outbound stuff, but this is still an early attempt, and far from being perfect.
Douane is far from being a perfect tool - but at the moment, it's the ONLY really useful tool in this regard. You can gain a more granular application control using tools like SELinux or AppArmor, but then, you don't really want to be using those, and for that matter, you don't want Douane either. But if paranoia is strong in this one, you will.
Personally, I'd simply not use software you don't trust, dialing home notwithstanding. Then, there are many security loopholes in the concept of outbound control and how it is enforced. However, within the narrow gap between reason and practice, Douane does its work okay, although I have not tested how it behaves under heavy traffic and stress. As far as the deployment goes, it's really alpha quality, with too many manual steps, too many bugs, and incomplete documentation. Plus you're loading stuff into memory and interfering with the network traffic, which can be tricky. But then, for those asking, is it doable, my answer is Douane. Corny, but I like it. Take care.