Docker y UFW pueden ser amigos

Si has intentado hacer funcionar docker junto a un firewall, te habrás dado cuenta de que todo falla estrepisomante. Docker juega con iptables y no le gusta que nadie se meta en medio.

Así pues vamos a ver como podemos configurar docker desde el principio hasta arreglar nuestros problemas con el firewall (UFW). Realmente este es el punto importante del post así que puedes ir directo si es lo que buscas

Nuevamente esto lo realizaremos en un servidor debian, pero a parte de este paso concreto en el que añadimos los repositorios concretos y usamos apt para la instalación, los demás pasos son iguales.

En cualquier caso, la guía ofcial es un buen punto de referencia.

Nota*: Este post pretende ser una referencia rápida para asegurarnos de que disponemos de un firewall a la para que podemos usar docker en nuestro servidor.

Instalación

Lo primero es asegurarnos de tener los paquetes necesarios para poder añadir el repositorio

$ sudo apt-get update

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

Una vez hecho eso añadimos la clave GPG oficial (os recomiendo comprobarlo en la web de docker, añadir repositorios externos puede abrir la puerta al malware en nuestro sistema. No os fies de un cualquiera en internet)

$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
Ejecutando el siguiente comando podremos comprobar  que la clave del repositorio coincide con la indicada en la guía oficial de Docker (9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88), y que el servidor es auténtico
$ sudo apt-key fingerprint 0EBFCD88


pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22

Una vez hecho eso añadimos finalmente el repositorio e instalamos docker engine

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

En distros con systemd habilitamos docker para iniciarse con el sistema

$ sudo systemctl enable docker

Convenciendo a Docker y a UFW para llevarse bien.

En nuestro caso como firewall usamos UFW, para asegurarnos de que no existan conflictos y todos los puertos que nadie fuera de nuestra red debe acceder queden efectivamente bloqueados.

Hasta donde yo se hay otras dos soluciones a este problema:

  • Evitar que Docker añada reglas iptables
  • Añadir reglas concretas en el firewall para permitir que una red concreta pueda accederse desde el exterior

Sin embargo, la primera acaba con la función de administración de red de Docker, y la segunda requiere añadir manualmente una regla cada vez que creamos una nueva red.

Sin embargo, con la siguiente aproximación, no encontramos ninguno de estos problemas. Bastaría con añadir lo siguiente al final del archivo /etc/ufw/after.rules (antes de COMMIT) 
# BEGIN UFW AND DOCKER

:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward

-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16

-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN

-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12

-A DOCKER-USER -j RETURN

-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP

Si estás interesado, he encontrado un post (en inglés) que explica esta configuración más en detalle.

Bueno, pues eso, en una burbuja a prueba de paquetes malvados, vivieron felices y comieron perdices…