O uso de regras iptables não está funcionando com o contêiner Docker

1

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

Enquanto pesquisava, percebi que muitas pessoas estão tendo esses problemas onde o tráfego para a porta encaminhada pelo Docker fica completamente exposto ao público e que eles não conseguem fazer o firewall corretamente.

Encontrei várias soluções nas últimas 6 horas, das quais nenhuma estava funcionando. Eu suponho que isso tenha algo a ver com a maneira como o Docker processa / encaminha o tráfego de entrada e meu conhecimento do iptables não é tão grande para que eu possa entender o que está acontecendo sozinho.

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: always

networks:
  es-network:
    driver: bridge

Estas são as regras do 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 acessado somente pelo 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

Eu tentei desabilitar o suporte ao iptables do Docker e desativar a rede de bridge e ajustar as regras do iptables algumas dúzias de vezes, mas sem sucesso.

Agradecemos qualquer sugestão e ajuda para que isso aconteça porque estou sem ideias e resultados de pesquisa para esse problema.

Obrigado antecipadamente!

    
por dzhi 29.01.2018 / 22:20

2 respostas

1

Para todos que procuram uma 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-prohibited

COMMIT

Encontrá-lo aqui: link

Funciona perfeitamente.

    
por 06.11.2018 / 12:55
1

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 PREROUTING 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 DOCKER, permitindo todo o tráfego enviado para o endereço IP e porta 8080 do contêiner.

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 quero filtrar o tráfego enviado para a porta 8080 (o tráfego para a porta 9010 foi processado pelo PREROUTING e agora é o tráfego enviado para a porta 8080) bloqueando todos os endereços IP enquanto permite 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 da cadeia FORWARD . Alternativamente, você pode substituir FORWARD por DOCKER.

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

Graças a essas regras, somente o IP 192.168.1.142 pode alcançar a porta 8080 usada pelo contêiner.

Para aqueles que visitarem essa resposta, se você quiser permitir apenas que um endereço IP específico acesse os contêineres, use o comando iptables sugerido no docentes do Docker .

    
por 30.01.2018 / 09:28