El uso de reglas de iptables no funciona con el contenedor Docker

Simplemente configure un contenedor ElasticSearch para usar con la aplicación Laravel de la empresa.Creación de docker-compose.yml y ejecutarlo es impecable y sencillo, pero el problema ocurre cuando quiero cortafuegos para que solo sea accesible desde una IP específica de la aplicación Laravel mencionada.

Mientras investigaba, noté que muchas personas tienen estos problemas en los que el tráfico al puerto reenviado por Docker queda completamente expuesto al público y que no pueden cortafuegos correctamente.

Encontré varios solución en las últimas 6 horas de las cuales ninguna estaba funcionando. Supongo que esto tiene algo que ver con la forma en que Docker procesa/reenvía el tráfico entrante y mi conocimiento de iptables no es tan vasto como para poder entender lo que está sucediendo por mi cuenta.

Este es mi docker-compose.yml (por lo que vale):

version: '3.4'services:  elasticsearch:    image: khezen/elasticsearch:6.1.1    container_name: elasticsearch    environment:      NETWORK_HOST: 0.0.0.0      HOSTS: 127.0.0.1      CLUSTER_NAME: fd-es      NODE_NAME: node-1      HEAP_SIZE: 31g      HTTP_SSL: "true"      ELASTIC_PWD: "somepasswd"      HTTP_CORS_ENABLE: "true"      HTTP_CORS_ALLOW_ORIGIN: /https?:\/\/localhost(:[0-9]+)?/    ulimits:      memlock:       soft: -1       hard: -1    volumes:      - ./config/elasticsearch.yml:/elasticsearch/config/elasticsearch.yml      - ./data:/elasticsearch/data      - ./logs:/elasticsearch/logs    ports:      - 9200:9200    networks:      - es-network    restart: alwaysnetworks:  es-network:    driver: bridge

Estas son mis reglas de iptables utilizadas actualmente, que son hasta cierto punto lo que quiero, pero todo el tráfico al puerto 9200 desde cualquier cliente aún se deja pasar en lugar de ser accesible solo desde mi aplicación:

*filter:INPUT DROP [0:0]:FORWARD DROP [0:0]:OUTPUT ACCEPT [779:162776]:DOCKER - [0:0]-A DOCKER -s xxx.xxx.xxx.xxx -p tcp -m tcp --dport 9200 -j ACCEPT-A DOCKER -o docker0 -p tcp -m tcp --dport 9200 -j ACCEPT-A DOCKER -p tcp --dport 9200 -j DROP-A INPUT -i lo -j ACCEPT-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT-A INPUT -m conntrack --ctstate INVALID -j DROP-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT-A INPUT -p udp -m conntrack --ctstate NEW -j ACCEPT-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j ACCEPT-A INPUT -p tcp -m tcp --dport 44344 -j ACCEPT-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable-A INPUT -p tcp -j REJECT --reject-with tcp-reset-A INPUT -j REJECT --reject-with icmp-proto-unreachable-A INPUT -j DROP

Intenté deshabilitar el soporte de iptables de Docker y deshabilitar las redes de puente y ajusté las reglas de iptables un par de docenas de veces, pero fue en vano.

Agradecería cualquier sugerencia y ayuda para que esto suceda porque no tengo ideas ni resultados de búsqueda para este problema.

Gracias de antemano!

Para todos los que buscan una solución a este problema, la respuesta es esta:

*filter:INPUT ACCEPT [0:0]:FORWARD DROP [0:0]:OUTPUT ACCEPT [0:0]:FILTERS - [0:0]:DOCKER-USER - [0:0]-F INPUT-F DOCKER-USER-F FILTERS-A INPUT -i lo -j ACCEPT-A INPUT -p icmp --icmp-type any -j ACCEPT-A INPUT -j FILTERS-A DOCKER-USER -i ens33 -j FILTERS-A FILTERS -m state --state ESTABLISHED,RELATED -j ACCEPT-A FILTERS -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT-A FILTERS -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT-A FILTERS -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT-A FILTERS -j REJECT --reject-with icmp-host-prohibitedCOMMIT

Lo encontré aquí: https://unrouted.io/2017/08/15/docker-firewall/

Funciona a la perfección.

Explicaré mi escenario en el que he probado lo que quieres lograr.

He lanzado un contenedor docker donde el puerto 9010 se reenvía al puerto 8080:

docker run -p 9010:8080 swaggerapi/swagger-editor

Docker crea una regla DNAT para la cadena de PREROUTING que reenvía el tráfico del puerto 9010 al puerto 8080:

DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:9010 to:172.17.0.5:8080

Docker también crea una regla en la cadena de DOCKER que permite todo el tráfico enviado a la dirección IP y al puerto 8080 del contenedor.

ACCEPT     tcp  --  !docker0 docker0  0.0.0.0/0            172.17.0.5           tcp dpt:8080

La cadena de la ventana acoplable se utiliza en la cadena de REENVÍO, donde todo el tráfico enviado al puente de la ventana acoplable 0 se procesa mediante reglas en la cadena de la ventana acoplable.

DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0

Ahora quiero filtrar el tráfico enviado al puerto 8080 (el tráfico al puerto 9010 ha sido procesado por el PREROUTING y ahora es el tráfico enviado al puerto 8080) bloqueando todas las direcciones IP al tiempo que permite el tráfico de la IP 192.168.1.142. La dirección IP del contenedor podría agregarse a esas reglas para aumentar la granularidad, por supuesto.

Añado las siguientes reglas al principio de la ADELANTE cadena. Alternativamente, puede reemplazar FORWARD con DOCKER.

iptables -I FORWARD -p tcp --dport 8080 -j DROPiptables -I FORWARD -p tcp -s 192.168.1.142 --dport 8080 -j ACCEPT

Gracias a esas reglas, solo IP 192.168.1.142 puede llegar al puerto 8080 utilizado por el contenedor.

Para aquellos que visitan esta respuesta, si solo desea permitir que una dirección IP específica acceda a los contenedores, use el comando iptables sugerido en el Documentos de Docker.

Creo que agregar esta línea habría solucionado su problema :

*filter:INPUT DROP [0:0]:FORWARD DROP [0:0]:OUTPUT ACCEPT [779:162776]:DOCKER - [0:0]**-A INPUT -p tcp -m tcp --dport 9200 -j DOCKER**-A DOCKER -s xxx.xxx.xxx.xxx -p tcp -m tcp --dport 9200 -j ACCEPT