docker-fw is a complementary tool for Docker to manage their iptables firewall rules; it features persistence of rules and dynamic port assignments, in case host or container are restarted.
docker-fw expects your firewall to be using the
*filter FORWARD chain with a default policy of REJECT/DROP (or an equivalent rule at bottom); this is default behavior starting from Docker version 1.5.
docker-fw does not work with Docker daemon
--restart options because docker-fw would not be called automatically on container start. However, you can customize initialization of containers on host boot script via
/etc/rc.local, for example to loop through existing containers and initialize their firewall rules using
It is also possible to use this utility completely manage your internal docker0 bridge traffic between containers, as it will play nicely along with
--iptables=true Docker daemon options.
Iptables workflow explanation
This is how docker-fw expects network flow to happen (e.g. iptables explained in human terms) under a strict whitelisting firewall:
- no link between FORWARD and DOCKER chains for all traffic from any source (rule
FORWARD -o docker0 -j DOCKERadded by Docker and removed by
- all internal traffic on FORWARD chain is linked to DOCKER chain (
FORWARD -i docker0 -o docker0 -j DOCKERas 1st rule)
- existing connections keep being forwarded (rule
FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPTadded by Docker is not touched)
- outgoing connections from all containers are kept being forwarded (
FORWARD -i docker0 ! -o docker0 -j ACCEPTadded by Docker is not touched)
- a DROP rule is appeneded on FORWARD table as exiting rule
- custom firewall rules are added before such DROP rule (usually with an insert) and/or to the DOCKER chain itself
See also example-iptables.txt.
Author is not officially involved with Docker development, thus this is not an official tool either.
docker-fw is licensed under GNU GPL version 2, see LICENSE.
make command should suffice. The Makefile will use a locally-generated
GOPATH without populating it with any package; all source code
dependencies are submodules under
Removes the iptables rule added by docker daemon at startup
-o docker0 -j DOCKER from
*filter FORWARD chain.
It will fail if docker daemon is not running or if rule does not exist.
'add' is used to add a firewall specification for a container (any network external to Docker circuit, e.g. 192.168.178.0/24 or a public internet address) and targets the FORWARD chain, while 'add-internal'/'add-two-ways' target the INPUT chain. If a valid container id/name is specified, then its IPv4 will be always aliased by docker-fw. Some special values exist for address specification:
.to reference the container for which rules are being added
/to reference the Docker host (usually 172.17.42.1)
NOTE: referencing the Docker host
/ is mostly intended for the 'add-internal' action; since it is considered a poor practice to create firewall rules to allow traffic that target the docker host
docker-fw add container-id --source=(22.214.171.124|.|container-id) [--rev-lookup] [--sport=xxxx] [--dest=(126.96.36.199|.|container-id)] [--dport=xxxx] [--protocol=(tcp|udp)] [--filter="-i docker0 -o docker0"] docker-fw (add-internal|add-two-ways) container-id --source=(188.8.131.52|.|container-id|/) [--rev-lookup] [--sport=xxxx] --dest=(184.108.40.206|.|container-id|/) --dport=xxxx [--protocol=(tcp|udp)] [--filter="-i docker0 -o docker0"]
Some rules to use 'add', 'add-two-ways', 'add-internal' and 'add-input':
- address specifications (source/destination) can also be in IPv4 subnet notation
--dportis mandatory for 'add-internal' action.
- protocol default is 'tcp'.
- at least source or destination must be equivalent to '.' (container for which rule is being specified), but cannot be both. If no destination is specified, '.' is assumed.
- specification of extra iptables filter is optional, and empty by default
--rev-lookupallows to specify a container IPv4 address, that otherwise would be an error (name/id form is preferred)
'add-two-ways' requires that source is a container and performs two tasks:
- execute add-internal with the specified rule
- always make sure that the source container will have a /etc/hosts rule for the source container
- the internal rules and the custom hosts will be restored when using
docker-fw startfor the container
These commands can also parse and add multiple rules from a file or stdin (using '-' as filename):
docker-fw add --from=(filename|-) docker-fw add-internal --from=(filename|-) docker-fw add-input --from=(filename|-)
--from, any other parameter (except
--rev-lookup) is disallowed.
An example of how to apply two-ways linking (assumes
--icc=false on your Docker daemon):
export IMAGE=ubuntu docker run --detach --name=promoted $IMAGE sleep 1000 docker run --detach --expose=1025 --link promoted:promoted --name=endpoint $IMAGE sleep 1000 ## enable iptables + hosts via docker-fw docker-fw add-two-ways endpoint --source promoted --dport 1025 ## test (it's advised to use 2 terminals for these commands) docker exec endpoint nc -l 1025 & docker exec promoted sh -c "echo 'Hello from promoted container' | nc endpoint 1025"
Save host configuration of a running and correctly network-enabled container. Such configuration will be used when starting the container through docker-fw. It always happens by default after a successful start.
docker-fw save-hostconfig container1 [container2] [container3] [...] [containerN]
Replay all firewall rules; will not add them again if existing on current iptables and will update the IPv4 addresses referenced in source/destination by looking up the aliases (if any specified).
--dry-run to display which stateful changes would be applied, and report exit code zero only if there would be none.
docker-fw replay [--dry-run] container1 [container2] [container3] [...] [containerN]
List all existing firewall rules for specified container(s); if no container is specified, all containers' rules will be displayed.
docker-fw ls [container1] [container2] [container3] [...] [containerN]
Drop all firewall rules for specified container; iptables rules are deleted and the json file that contains them is deleted from the container directory.
docker-fw drop container1 [container2] [container3] [...] [containerN]
Allow specified source address (external) as an 'add' command for each of the available published ports of the container.
docker-fw allow container-id ip-address-1 [ip-address-2] [ip-address-3] [...] [ip-address-N]
This command is explicitly meant to allow access from external networks to the container's network address.
docker-fw start [--dry-run] [--paused] [--pull-deps] container1 [container2] [container3] [...] [containerN]
It does the following:
- sort input list of containers second their dependencies
- start each of them sequentially (paused when
- execute the equivalent of 'replay' action for each container as it is started
--paused allows to start containers in paused status (for example in case user doesn't want to allow any activity until all firewall restore operations are completed).
--pull-deps will automatically make dependant (by link relationship) containers part of the selection.
If a container is already started or paused, its state is not changed.
--dry-run containers will be displayed in the order they would be started, but their state will not be changed.
Please note that Docker currently (1.8) lacks a correct dependency DAG when starting containers, thus it does not start them in correct order (unless you use
--restart=true has a hack); unfortunately, nothing is mentioned in documentation there regarding this issue, which is solved as explained above by docker-fw start action (even if you don't use any of the other docker-fw features).
docker-fw uses Docker API through go-dockerclient, and command-line based iptables access; libiptc is not being used because its API is not published (and it would be a tad too complex, see also go-libiptc).
Container information is retrieved via API when needed and cached for the duration of the execution of docker-fw. Any id/name valid for the Docker API can be used with docker-fw.
- Has some hardcoded features/settings inherited from Docker defaults (e.g. 172.x.x.x subnet)
- Not thoroughly tested, and no unit tests coverage
- Stores its
.jsondescriptors in Docker's own containers metadata directory
All of the above can be addressed with some effort, and probably will (in due time); as always, patches welcome!
If you see an error like this when running
2015/01/24 21:01:20 init: Could not find docker-added rule
You have two issues: