2016
04.19

The problem with docker is it opens up ports in the firewall to the world, that’s fine if you want the app running in the container available to world + dog but in my case I didn’t, also this is on a hosted box elsewhere that sadly isn’t infront of a dedicated firewall, infant a dedicated firewall would probably cost more than the entire server itself as it was a very cheap server.

 

Because it’s running on a very low end box I couldn’t even run a KVM hypervisor and run a firewall infront of the docker host that way (Which is my preferred option if running on a dedi with no hardware f/w infront).

I could have disabled dockers tampering with iptables but it’s handy to have it do the NAT stuff automatically, instead this is a horrible hack that will inject a new forward rule above the docker rules after restart.

This assumes a few things here, that you are using SystemD, FirewallD is disabled the internet uplink is eth0.

You will also need the iptables-persistent package installed

 

I don’t claim this to be a secure setup, but it should be a bit more secure than the default I’d be wary of trusting it for anything with access to sensitive data,  ideally you’d want an external firewall infront of the Docker host if you plan to allow docker to have it’s way with the machines own firewall.

Below is a slightly modified version of my /etc/iptables/rules.v4 , Currently I’m only allowing access from certain IP’s although I expect to expand this later, it was a basic ruleset for testing

*filter

:INPUT DROP [0:0]

:FORWARD DROP [0:0]

:OUTPUT ACCEPT [0:0]

-A INPUT -i docker0 -j ACCEPT

-A INPUT -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p icmp –icmp-type echo-request -j ACCEPT

-A INPUT -s <My IP 1> -j ACCEPT

-A INPUT -s <My IP 2> -j ACCEPT

-N DOCKER-SEC

-A DOCKER-SEC -s <My IP 1>-j RETURN

-A DOCKER-SEC -m conntrack –ctstate RELATED,ESTABLISHED -j RETURN

-A DOCKER-SEC -s <MY IP 2> -j RETURN

-A DOCKER-SEC -i eth0 -j DROP

-A DOCKER-SEC -j RETURN

COMMIT

What this does is setup an IPtables ruleset that allow my IP’s access to the server and drops everything else, it also creates a DOCKER-SEC chain that filters traffic from the internet into the docker containers…

Then I created the following script in /lib/systemd/system/docker-firewall-mod.service

[Unit]

Description=fix for docker opening the firewall to world and dog

[Service]

ExecStart=/scripts/fix-firewall.sh &

[Install]

after=docker.service

The content of /scripts/fixfirewall.sh – hey I did say it was a horrible hackjob

#!/bin/bash

# A Post docker start script to inject a new table to stop docker mess up the firewall, I’d disable dockers firewall mod support but I kinda want to to make the nat rules

# Ideally this should be done during the iptables laod but then this rule ends up below the docker created rules and everything is wired open, arrg.

# Begin injection

sleep 30

/sbin/iptables -I FORWARD 1 -o docker0 -j DOCKER-SEC

P.s I’ve actually cleaned up those comments in the description’s for the service/comments in the script the original wasn’t quite so polite about it 😉

Also note that there will be a brief window before this gets injected that containers will be exposed to the world.

Also using

iptables-restore < /etc/iptables/rules.v4

to add rules will remove the docker stuff from the firewall which seems to require a restart to docker to fix.