Buscar..


Introducción

Este tema trata sobre cómo limitar el acceso a sus contenedores de la ventana acoplable desde el mundo exterior utilizando iptables.

Para las personas impacientes, puedes consultar los ejemplos. Para los demás, lea la sección de comentarios para comprender cómo crear nuevas reglas.

Sintaxis

  • iptables -I DOCKER [REGLA ...] [ACCEPT | DROP] // Para agregar una regla a la parte superior de la tabla DOCKER
  • iptables -D DOCKER [REGLA ...] [ACCEPT | DROP] // Para eliminar una regla de la tabla DOCKER
  • ipset restore </etc/ipfriends.conf // Para reconfigurar los ipset ipfriends

Parámetros

Parámetros Detalles
ext_if Su interfaz externa en el host Docker.
XXX.XXX.XXX.XXX Se debe dar una IP particular a la cual los contenedores de Docker acceden.
YYY.YYY.YYY.YYY Se debe proporcionar otra IP a la que accedan los contenedores Docker.
ipfriends El nombre del conjunto de ipsets que define las direcciones IP permitidas para acceder a sus contenedores de Docker.

Observaciones

El problema

Configurar las reglas de iptables para los contenedores Docker es un poco complicado. Al principio, usted pensaría que las reglas de firewall "clásicas" deberían hacer el truco.

Por ejemplo, supongamos que ha configurado un contenedor nginx-proxy + varios contenedores de servicio para exponer a través de HTTPS algunos servicios web personales. Entonces, una regla como esta debería dar acceso a sus servicios web solo para IP XXX.XXX.XXX.XXX.

$ iptables -A INPUT -i eth0 -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
$ iptables -P INPUT DROP

No funcionará, sus contenedores siguen siendo accesibles para todos.

De hecho, los contenedores Docker no son servicios de host. Se basan en una red virtual en su host, y el host actúa como una puerta de enlace para esta red. Y con respecto a las puertas de enlace, el tráfico enrutado no se maneja con la tabla INPUT, sino con la tabla FORWARD, que hace que la regla publicada antes sea inefectiva.

Pero no es todo. De hecho, el demonio Docker crea muchas reglas de iptables cuando comienza a hacer su magia con respecto a la conectividad de la red de contenedores. En particular, se crea una tabla DOCKER para manejar las reglas relativas a los contenedores al reenviar el tráfico de la tabla FORWARD a esta nueva tabla.

$ iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:https
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:http

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

La solución

Si verifica la documentación oficial ( https://docs.docker.com/v1.5/articles/networking/) , se ofrece una primera solución para limitar el acceso del contenedor Docker a una IP particular.

$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

De hecho, agregar una regla en la parte superior de la tabla DOCKER es una buena idea. No interfiere con las reglas configuradas automáticamente por Docker, y es simple. Pero faltan dos grandes:

  • Primero, ¿qué sucede si necesita acceder desde dos IP en lugar de una? Aquí solo se puede aceptar un src IP, el otro se eliminará sin ninguna forma de evitarlo.
  • En segundo lugar, ¿qué pasa si su docker necesita acceso a Internet? Prácticamente ninguna solicitud tendrá éxito, ya que solo el servidor 8.8.8.8 podría responder a ellos.
  • Por último, ¿y si quieres añadir otras lógicas? Por ejemplo, dé acceso a cualquier usuario a su servidor web que sirve en el protocolo HTTP, pero limite todo lo demás a una IP particular.

Para la primera observación, podemos usar ipset . En lugar de permitir una IP en la regla anterior, permitimos todas las IP desde el conjunto de datos predefinido. Como beneficio adicional, el ipset se puede actualizar sin la necesidad de redefinir la regla de iptable.

$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP

Para la segunda observación, este es un problema canónico para los firewalls: si se le permite comunicarse con un servidor a través de un firewall, entonces el firewall debe autorizar al servidor a responder a su solicitud. Esto se puede hacer mediante la autorización de paquetes que están relacionados con una conexión establecida. Para la lógica docker, da:

$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

La última observación se centra en un punto: las reglas de iptables son esenciales. De hecho, la lógica adicional para ACEPTAR algunas conexiones (incluida la que concierne a las conexiones ESTABLECIDAS) debe colocarse en la parte superior de la tabla DOCKER, antes de la regla DROP que niega todas las conexiones restantes que no coincidan con el conjunto de cambios.

Como usamos la opción -I de iptable, que inserta reglas en la parte superior de la tabla, las reglas de iptables anteriores deben insertarse en orden inverso:

// Drop rule for non matching IPs
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
// Then Accept rules for established connections
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT 
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 3rd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 2nd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 1st custom accept rule

Con todo esto en mente, ahora puede consultar los ejemplos que ilustran esta configuración.

Limite el acceso en los contenedores Docker a un conjunto de IPs

Primero, instale el ipset si es necesario. Por favor refiérase a su distribución para saber cómo hacerlo. Como ejemplo, aquí está el comando para distribuciones similares a Debian.

$ apt-get update
$ apt-get install ipset

Luego cree un archivo de configuración para definir un ipset que contenga las IP para las que desea abrir el acceso a sus contenedores de Docker.

$ vi /etc/ipfriends.conf
# Recreate the ipset if needed, and flush all entries
create -exist ipfriends hash:ip family inet hashsize 1024 maxelem 65536
flush
# Give access to specific ips
add ipfriends XXX.XXX.XXX.XXX
add ipfriends YYY.YYY.YYY.YYY

Cargue este ipset.

$ ipset restore < /etc/ipfriends.conf

Asegúrese de que su demonio Docker se esté ejecutando: no se debe mostrar ningún error después de ingresar el siguiente comando.

$ docker ps

Estás listo para insertar tus reglas de iptables. Debe respetar el orden.

// All requests of src ips not matching the ones from ipset ipfriends will be dropped.
$ iptables -I DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
// Except for requests coming from a connection already established.
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Si desea crear nuevas reglas, deberá eliminar todas las reglas personalizadas que haya agregado antes de insertar las nuevas.

$ iptables -D DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
$ iptables -D DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Configurar acceso de restricción cuando se inicia el demonio Docker

Trabajo en progreso

Algunas reglas personalizadas de iptables

Trabajo en progreso



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow