Назад | Перейти на главную страницу

Использование правил iptables не работает с контейнером Docker

Просто настройте контейнер ElasticSearch для использования с приложением Laravel компании. Создание и запуск docker-compose.yml безупречно и просто, но проблема возникает, когда я хочу установить брандмауэр на эту вещь, чтобы она была доступна только с одного конкретного IP-адреса упомянутого приложения Laravel.

Во время исследования я заметил, что многие люди сталкиваются с такими проблемами, когда трафик на порт, перенаправляемый Docker, становится полностью открытым, и что они не могут правильно его защитить.

Я нашел несколько решения за последние 6 часов, из которых никто не работал. Я предполагаю, что это как-то связано с тем, как Docker обрабатывает / перенаправляет входящий трафик, и мои знания iptables не так обширны, чтобы я мог самостоятельно понять, что происходит.

Это мой docker-compose.yml (за что это стоит):

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

Это мои используемые в настоящее время правила iptables, которые в некоторой степени являются тем, что я хочу, но весь трафик на порт 9200 от любого клиента по-прежнему пропускается, а не доступен только из моего приложения:

*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

Я пытался отключить поддержку Docker iptables и мостовую сеть и несколько десятков раз настраивал правила iptables, но безрезультатно.

Буду признателен за любое предложение и помощь, потому что у меня нет идей и результатов поиска по этой проблеме.

Заранее спасибо!

Для всех, кто ищет решение этой проблемы, ответ такой:

*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

Нашел здесь: https://unrouted.io/2017/08/15/docker-firewall/

Прекрасно работает.

Я объясню свой сценарий, в котором я тестировал то, чего вы хотите достичь.

Я запустил док-контейнер, в котором порт 9010 перенаправлен на порт 8080:

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

Docker создает правило DNAT для цепочки PREROUTING, которое перенаправляет трафик с порта 9010 на порт 8080:

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

Docker также создает правило в цепочке DOCKER, разрешающее весь трафик, отправляемый на IP-адрес контейнера и порт 8080.

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

Цепочка DOCKER используется в цепочке FORWARD, где весь трафик, отправляемый на мост docker0, обрабатывается правилами в цепочке DOCKER.

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

Теперь я хочу фильтровать трафик, отправляемый на порт 8080 (трафик на порт 9010 был обработан PREROUTING, и теперь он отправляется на порт 8080), блокируя все IP-адреса, разрешая трафик с IP 192.168.1.142. Конечно, IP-адрес контейнера может быть добавлен к этим правилам для большей детализации.

Я добавляю следующие правила в начало ВПЕРЕД цепь. В качестве альтернативы вы можете заменить FORWARD на DOCKER.

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

Благодаря этим правилам только IP 192.168.1.142 может получить доступ к порту 8080, используемому контейнером.

Для тех, кто посещает этот ответ, если вы хотите разрешить доступ к контейнерам только одному определенному IP-адресу, используйте команду iptables, предложенную в Документы Docker.