Usar regras iptables não está funcionando com o contêiner Docker

Basta configurar um contêiner ElasticSearch para usar com o aplicativo Laravel da empresa.Criando docker-compose.yml e executá-lo é impecável e direto, mas o problema ocorre quando quero firewall essa coisa para que seja acessível apenas a partir de um IP específico do aplicativo Laravel mencionado.

Ao pesquisar, notei que muitas pessoas estão tendo esses problemas em que o tráfego para a porta encaminhado pelo Docker fica completamente exposto ao público e que não conseguem firewall corretamente.

Encontrei vários solucao nas últimas 6 horas, nenhuma estava funcionando. Presumo que isso tenha algo a ver com a maneira como o Docker processa/encaminha o tráfego de entrada e meu conhecimento iptables não é tão vasto para que eu possa entender o que está acontecendo por conta própria.

Este é o meu docker-compose.yml (pelo que vale a pena):

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 são as minhas regras iptables usadas atualmente, que são até certo ponto o que eu quero, mas todo o tráfego para a porta 9200 de qualquer cliente ainda é permitido em vez de ser acessível apenas a partir do meu aplicativo:

*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

Tentei desabilitar o suporte iptables do Docker e desabilitar a rede de ponte e ajustei as regras iptables algumas dezenas de vezes, mas sem sucesso.

Eu apreciaria qualquer sugestão e ajudaria a fazer isso acontecer porque estou sem ideias e resultados de pesquisa para esse problema.

Obrigado antecipadamente!

Para todos que procuram solução para este problema, a resposta é 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

Encontrei aqui: https://unrouted.io/2017/08/15/docker-firewall/

Funciona perfeitamente.

Vou explicar meu cenário em que testei o que você deseja alcançar.

Eu lancei um contêiner docker onde a porta 9010 é encaminhada para a porta 8080:

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

O Docker cria uma regra DNAT para a cadeia de pré-reconhecimento que encaminha o tráfego da porta 9010 para a porta 8080:

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

O Docker também cria uma regra na cadeia do DOCKER permitindo que todo o tráfego seja enviado para o endereço IP do contêiner e para a porta 8080.

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

A cadeia DOCKER é usada na cadeia FORWARD, onde todo o tráfego enviado para a ponte docker0 é processado por regras na cadeia DOCKER.

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

Agora eu quero filtrar o tráfego enviado à porta 8080 (o tráfego à porta 9010 foi processado pelo PREROUTING e agora é tráfego enviado à porta 8080) obstruindo todos os endereços IP ao permitir o tráfego do IP 192.168.1.142. O endereço IP do contêiner pode ser adicionado a essas regras para maior granularidade, é claro.

Eu adiciono as seguintes regras no início do FRENTE cadeia. Alternativamente, você pode substituir o FORWARD pelo DOCKER.

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

Graças a essas regras, apenas o IP 192.168.1.142 pode atingir a porta 8080 usada pelo contêiner.

Para aqueles que visitam esta resposta, Se você deseja apenas permitir que um endereço IP específico acesse os contêineres, use o comando iptables sugerido no Docker docs.

Acho que adicionar esta linha teria corrigido seu 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