Docker con firewall (iptables=false)

Docker con iptables=false

Configurando Docker en nuestro servidor nos dimos cuenta que teníamos un problema, Docker crea por defecto las reglas necesarias en iptables para poder acceder a los contenedores desde todas las interfaces y el resto del universo.

Nosotros tenemos securizadas las conexiones de la máquina con APF, un firewall basado en conjunto de scripts que mediante un fichero de configuración se encarga de generar las reglas de iptables simplificando la tediosa tarea de configuración iptables. A pesar de tener bloqueados los puertos expuestos de los contenedores mediante el firewall, nos dimos cuenta que los puertos estaban expuestos a internet.

Para evitar este problema la mejor solución es desactivar el uso de iptables por parte de Docker. Para ello hay que añadir la configuración iptables=false al demonio de docker. En nuestro caso como el servidor es Debian hemos tenido que añadir la configuración en formato JSON al fichero /etc/docker/daemon.json.

# modificamos (o creamos) el fichero de configuración
nano /etc/docker/daemon.json

# START - Contenido del fichero
{
"iptables": false
}
# END - Contenido del fichero

# reiniciamos el servicio docker
/etc/init.d/docker restart

A partir de este momento cuando se arranque un contenedor los puertos expuestos en la máquina no serán accesibles desde internet.

¡Un problema menos! Genial, nos vemos en la siguiente entrada…. espera, espera… parece que tenemos un problema. Con esta operación hemos perdido la conectividad desde los contedores a internet 🙁.

Conectividad de los contendores a internet

Tenemos un problema pero también la solución, podemos añadir a iptables las reglas necesarias para poder acceder a internet desde los contenedores. Ejecutando los siguientes comandos conseguimos tener conectividad a internet desde los contenedores.

iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
iptables -t filter -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
iptables -t filter -A FORWARD -i docker0 -o docker0 -j ACCEPT

Si como en nuestro caso utilizas un firewall externo como APF, cada vez que lo recargues las reglas necesarias para Docker se perderán.

En el caso de APF hay una forma de persistir estas reglas, añadiéndolas al fichero /etc/apf/postroute.rules se ejecutarán justo después de haberse creado todas las reglas generadas por APF.

Añadiendo al final del fichero las siguientes líneas cada vez que arranquemos APF también se cargarán las reglas necesarias por Docker 😀

# editamos el fichero añadiendo al final
nano /etc/apf/postroute.rules

# START - PEGAR AL FINAL DEL FICHERO
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
iptables -t filter -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
iptables -t filter -A FORWARD -i docker0 -o docker0 -j ACCEPT
# END - PEGAR AL FINAL DEL FICHERO

Redes personalizadas Docker

En el caso de utilizar redes personalizadas docker para establecer la conectividad de nuestros contenedores tenemos un problema, con la configuración actual no tenemos conectividad a internet. Si queremos tener salida a internet desde estos contenedores, tendremos que añadir una configuración adicional a iptables.

Antes de poder ejecutar las reglas necesitamos saber los rangos IP de estas redes docker personalizadas. En nuestro caso tenemos 2 redes personalizadas de tipo bridge, como todas estas redes comienzan por br- podemos ejecutar el siguiente comando para ver los rangos de las redes:

# comando
basename -a /sys/class/net/* | grep br- | xargs -n 1 ip -f inet addr show | grep -Po 'inet \K[^ ]+'
# resultado
172.18.0.1/16
172.19.0.1/16

Con eso podemos ver que en nuestro caso las redes bridge de docker son 172.18.0.1 y 172.19.0.1. Ahora que sabemos los rangos podemos ejecutar las reglas de iptables:

iptables -t nat -A POSTROUTING -s 172.18.0.0/16 ! -o docker0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 172.19.0.0/16 ! -o docker0 -j MASQUERADE

 

Espero que os haya sido de ayuda. ¡Nos vemos!

Sobre el autor

Apasionado de las tecnologías, entusiasta del desarrollo de software. Especializado en Java EE. Cofundador de www.logrosxbox.com.