Sin conectividad de red hacia / desde el contenedor Docker CE en CentOS 8

Acabo de instalar la última versión de docker-ce en CentOS, pero yo no se puede acceder a los puertos publicados desde un servidor vecino y no puede llegar al exterior desde el propio contenedor.

Ejecutando un CentOS 8 de vainilla simple con NetworkManager y FirewallD habilitados. La zona de firewall predeterminada es public.

Versiones:

  • docker-ce 19.03.3 (RPM oficial de Docker)
  • containerd.io 1.2.6 (RPM oficial de Docker para CentOS 7 - aún no disponible para CentOS 8)
  • CentOS 8.0.1905 (instalación mínima)

Lo que falta en las respuestas anteriores es el hecho de que primero debe agregar su interfaz docker a la zona que configura, por ejemplo, pública (o agregarla a la zona "confiable" que se sugirió aqui pero dudo que sea prudente, desde una perspectiva de seguridad). Porque por defecto no está asignado a una zona. También recuerde volver a cargar el demonio de la ventana acoplable cuando haya terminado.

# Check what interface docker is using, e.g. 'docker0'ip link show# Check available firewalld zones, e.g. 'public'sudo firewall-cmd --get-active-zones# Check what zone the docker interface it bound to, most likely 'no zone' yetsudo firewall-cmd --get-zone-of-interface=docker0# So add the 'docker0' interface to the 'public' zone. Changes will be visible only after firewalld reloadsudo nmcli connection modify docker0 connection.zone public# Masquerading allows for docker ingress and egress (this is the juicy bit)sudo firewall-cmd --zone=public --add-masquerade --permanent# Optional open required incomming ports (wasn't required in my tests)# sudo firewall-cmd --zone=public --add-port=443/tcp# Reload firewalldsudo firewall-cmd --reload# Reload dockerdsudo systemctl restart docker# Test ping and DNS works:docker run busybox ping -c 1 172.16.0.1docker run busybox cat /etc/resolv.confdocker run busybox ping -c 1 yourhost.local

Para poder establecer reglas detalladas para Docker, no necesitaba establecer docker0 en ninguna zona.

# 1. Stop Dockersystemctl stop docker
# 2. Recreate DOCKER-USER chain in firewalld. firewall-cmd --permanent \             --direct \             --remove-chain ipv4 filter DOCKER-USERfirewall-cmd --permanent \             --direct \             --remove-rules ipv4 filter DOCKER-USERfirewall-cmd --permanent \             --direct \             --add-chain ipv4 filter DOCKER-USER# (Ignore any warnings)
# 3. Docker Container <-> Container communicationfirewall-cmd --permanent \             --direct \             --add-rule ipv4 filter DOCKER-USER 1 \             -m conntrack --ctstate RELATED,ESTABLISHED \             -j ACCEPT \             -m comment \             --comment 'Allow docker containers to connect to the outside world'firewall-cmd --permanent \             --direct \             --add-rule ipv4 filter DOCKER-USER 1 \             -j RETURN \             -s 172.17.0.0/16 \             -m comment \             --comment 'allow internal docker communication'# Change the Docker Subnet to your actual one (e.g. 172.18.0.0/16)
# 4. Add rules for IPs allowed to access the Docker exposed ports.firewall-cmd --permanent \             --direct \             --add-rule ipv4 filter DOCKER-USER 1 \             -o docker0 \             -p tcp \             -m multiport \             --dports 80,443 \             -i eth0 \             -o docker0 \             -s 1.2.3.4/32 \             -j ACCEPT \             -m comment \             --comment 'Allow IP 1.2.3.4 to docker ports 80 and 443'
# 5. log docker traffic (if you like)firewall-cmd --direct \             --add-rule ipv4 filter DOCKER-USER 0 \             -j LOG \             --log-prefix ' DOCKER: '
# 6. Block all other IPs. This rule has lowest precedence, so you can add allowed IP rules later.firewall-cmd --permanent \             --direct \             --add-rule ipv4 filter DOCKER-USER 10 \             -j REJECT \             -m comment \             --comment 'reject all other traffic to DOCKER-USER'
# 7. Reload firewalld, Start Docker againfirewall-cmd --reloadsystemctl start docker

Esto termina en reglas definidas en /etc/firewalld / direct.XML:

<?xml version="1.0" encoding="utf-8"?><direct>  <chain ipv="ipv4" table="filter" chain="DOCKER-USER"/>  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment 'Allow docker containers to connect to the outside world'</rule>  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-j RETURN -s 172.17.0.0/16 -m comment --comment 'allow internal docker communication'</rule>  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-p tcp -m multiport --dports 80,443 -s 1.2.3.4/32 -j ACCEPT -m comment --comment 'Allow IP 1.2.3.4 to docker ports 80 and 443'</rule>  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-j LOG --log-prefix ' DOCKER TCP: '</rule>  <rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="10">-j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'</rule></direct>

El inconveniente sigue siendo que necesita instalar containerd.io de CentOS7 según lo declarado por Saustrup

He cambiado la variable FirewallBackend a iptables nuevamente y funciona para mí.

Con esta actualización, el subsistema de filtrado nftables es el backend de firewall predeterminado para el demonio firewalld. Para cambiar el backend, use la opción FirewallBackend en /etc/firewalld.archivo conf.

Enlace: Funcionalidad obsoleta de Centos8

No tengo demasiada información sobre este cambio de comportamiento. Algunas de las reglas de iptables que Docker intenta usar no funcionan de acuerdo con los registros de CentOS8:

ADVERTENCIA: COMMAND_FAILED:' /usr/sbin/iptables-w10-D FORWARD-i docker0-o docker0-j DROP ' failed: iptables: regla incorrecta (¿existe una regla coincidente en esa cadena?).

El mío ni siquiera funciona con Firewalld completamente deshabilitado. Alguien tiene alguna idea ??