pbuilder firewall setup

For many years I have maintained firewalls on my servers that prevent processes from being able to connect to the outside world, with a specific whitelist of exceptions. This is easy to do using the excellent ferm:

And here's the result:

Most of the matching rules use the owner match extension to ensure that only processes running with the correct user id are able to connect out. Unfortunately, I ran into a problem when running apt 1.4 inside a pbuilder chroot.

The problem

Attempts to set up a new pbuilder chroot using Debian 9 ("stretch") failed with a strange error from apt:

This was caused by the firewall blocking the connection:

But why is the connection being attempted by a process with such a strange uid?

The gid from the log message doesn't even match uuidd's group, but rather:

It turns out that these are only the values from /etc/passwd and /etc/group from outside the chroot set up by pbuilder. On the inside, we see something else:

It turns out that since version 1.1~exp3, apt has used an unprivileged user for tasks such as downloading packages, and so I will have to figure out how to allow this user to pass through the firewall.

The obvious solution would be to allow outgoing connections for uid 100, but this is not ideal:

A better solution would be to allow the firewall to recognize that that a packet originates from a process running within a pbuilder chroot, and permit it to pass.

The solution

The net_cls cgroup can be used to assign a 'class identifier' (classid) to any packet transmitted by a process within a cgroup. iptables can then be configured to match on this classid. I have chosen the arbitrary classid 10:10 for this example.

First, I needed to make sure that the net_cls hierarchy was mounted during boot. This was the easiest step because I am using systemd which mounts all available cgroup controllers by default:

Next I needed some firewall rules. I added support for the cgroup match module to ferm, and updated my rules with the following:

Then I modified the systemd unit for my Buildbot worker to create the /pbuilder cgroup within the net_cls hierarchy and assign the 10:10 classid to processes within it.

The final piece of the puzzle is to ensure that the Buildbot worker actaully runs pbuilder build inside the net_cls hiarchy's /pbuilder cgroup when it kicks off a package build. This is done with the cgexec command:


robots.org.uk: PbuilderFirewallSetup (last edited 2017-03-19 10:19:38 by sam)

© Sam Morris <sam@robots.org.uk>.
Content may be distributed and modified providing this notice is preserved.