Unsubstantiated Opinions and Meaningless Blather

Making Docker Play Nice with Ferm Firewalls on Linux

I’ve been using Docker a fair bit for work at ActiveState recently. It’s quite nice and makes creating and deploying services much simpler.

However, it can also be incredibly annoying when I’m using it locally on my desktop. By default, the Docker daemon (dockerd) messes with iptables in order to allow docker images to connect to the interwebs. But if you already have a firewall in place there’s a good chance that this won’t work. So every time I want to use Docker I disable my ferm-based firewall and restart the Docker daemon. Then when I’m done using Docker I bring the firewall back up. Tedious and unsafe!

Figuring Out What dockerd Does

Docker creates a new virtual network interface named docker0 and then sets up iptables to give this interface access to the internet. I could not find any documentation on what dockerd actually does with iptables. Fortunately, this is easy to figure out by dumping the iptables rules when dockerd is running:

The next step is to translate this into ferm rules and integrate it into my existing ferm config.

Making It Work

Since I wanted to make ferm set up the Docker rules, I had to tell dockerd to stop doing it itself when the daemon was started.

Depending on what init system you’re using, there are two ways pass options to dockerd. If your system is using systemd, the daemon is configured via the /etc/docker/daemon.json. This disables the iptables setup:

daemon.json

JavaScript

1

2

3

{

"iptables":false

}

For other init systems (sysv and upstart) you should edit /etc/default/docker and add --iptables=false to DOCKER_OPTS.

The Docker rules translate to the following ferm config (disclaimer: I am not an iptables or ferm expert so this may be a bit wrong):

docker rules in ferm

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

domain ip {

table nat {

chain DOCKER {

interface docker0 RETURN;

}

chain PREROUTING {

mod addrtype dst-type LOCAL jump DOCKER;

}

chain POSTROUTING {

saddr 172.17.0.0./16 outerface !docker0 MASQUERADE;

}

chain OUTPUT {

destination !127.0.0.0/8 {

mod addrtype dst-type LOCAL jump DOCKER;

}

}

}

table filter {

chain DOCKER {

}

chain DOCKER-USER {

}

chain DOCKER-ISOLATION-STAGE-1 {

interface docker0 outerface !docker0 jump DOCKER-ISOLATION-STAGE-2;

RETURN;

}

chain DOCKER-ISOLATION-STAGE-2 {

outerface docker0 DROP;

RETURN;

}

chain FORWARD {

jump DOCKER-USER;

jump DOCKER-ISOLATION-STAGE-1;

outerface docker0 ACCEPT;

outerface docker0 jump DOCKER;

interface docker0 outerface !docker0 ACCEPT;

interface docker0 outerface docker0 ACCEPT;

}

}

}

A Not So Great Solution

This works. I can enable my firewall with sudo service ferm restart and use Docker normally. Containers are able to access the internet. Yay!

One problem, however, is that the easiest way to make this work was to put the docker rules before all my other rules. This probably means my docker containers are a bit more exposed than is ideal. However, I only use Docker to build containers and test them locally, so that’s okay for now.

But the bigger problem is that this will almost certainly break. In the short time I’ve been using Docker (about 6 months) the way it does networking has changed at least once. A few months back dockerd would set up two virtual interfaces, docker0 and docker_gwbridge. The iptables rules it used were a bit different then as well.

So it seems likely that dockerd might change what it does again and my config will be broken. This is all quite annoying. I’m not sure what the best solution is, but at the very least it’d be good to see Docker document exactly what these rules need to be (and better yet, what they’re doing at a higher level).

Comments are closed.

Post navigation

About

This is Dave Rolsky's blog. It contains blog posts. These posts contain ideas, mostly in the form of words. The words are made of letters, and each letter is made of pixels. The pixels are made of turtles.