Monday, August 5, 2019

Docker firewalling

Docker containers are not host services. They rely on a virtual network in your host, and the host acts as a gateway for this network. So traffic is routed traffic and FORWARD chain/table is used.
In fact Docker daemon creates several iptables-chains to setup containers connectivity and we can use DOCKER chain to control access to the Docker Containers. Traffic from FORWARD chain is forwarded to the DOCKER chain. You should not modify the rules Docker adds to your iptables policies. For manually added rules you must use DOCKER-USER chain. Rules from the DOCKER-USER chain are used before DOCKER chain rules.

To restrict access to container which uses docker bridge network (inserts rule to the first position in the rules list):
add rule: iptables -I DOCKER-USER ruleHere -j [ACCEPT|DROP]
remove rule: iptables -D DOCKER-USER ruleNumberHere

For example:
list all rules in DOCKER-USER chain:
iptables -L DOCKER-USER
or more verbose with numeric ports:
iptables -L DOCKER-USER -vn
deny access to all containers from IP address 10.10.10.11:
iptables -I DOCKER-USER -s 10.10.10.11 -j DROP
deny access to the containers TCP port 5000 (this port is container port, not host port of the port-mapping):
iptables -I DOCKER-USER -p tcp -m tcp --dport 5000 -j DROP

macvlan driver

Below (till the end of the blog-post) can be used for any container not just using macvlan driver .

With network namespaces, you can have different and separate instances of network interfaces and routing tables that operate independent of each other.
The only namespace we have on each linux machine is a "default" or "global" namespace (physical interfaces exist here).

From the docker-host:


Make directory for network namespaces linking (done on the container host only once):
mkdir -p /var/run/netns

Find PID of the container:
CPID=$(docker inspect --format='{{ .State.Pid }}' containerName)

Create linking
LINK="/var/run/netns/$CPID"
ln -s "/proc/$CPID/ns/net" "$LINK"

All container related proc entries are under:
/proc/$CPID/ns/net

Drop packets on found container PID:
ip netns exec $CPID iptables -I INPUT -j DROP
ip netns exec $CPID iptables -I OUTPUT -j DROP

Allow only incoming and outgoing ICMP packets:
ip netns exec $CPID iptables -I INPUT  -j ACCEPT
ip netns exec $CPID iptables -I OUTPUT -j ACCEPT

Viewing all container iptables rules:
ip netns exec $CPID iptables -L

rm -f $LINK

From the container itself:


To use iptables inside container itself, you must run container with NET_ADMIN privilege
docker run --cap-add=NET_ADMIN --name='ctr0' --hostname='ctr0' -it centos /bin/bash

From the container bash:
yum install net-tools
yum install iptables

Now you can restrict all access but ICMP:
iptables -I INPUT -j DROP
iptables -I OUTPUT -j DROP
iptables -I INPUT -p icmp  -j ACCEPT
iptables -I OUTPUT -p icmp  -j ACCEPT
iptables -L

No comments:

Post a Comment