Правила использования 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: alwaysnetworks:  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

Я пытался отключить поддержку iptables в Docker и отключить мостовую сеть, а также пару десятков раз менял правила 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-prohibitedCOMMIT

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

Работает отлично.

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

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

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

Docker создает правило DNAT для цепочки ПРЕДВАРИТЕЛЬНОЙ МАРШРУТИЗАЦИИ, которая перенаправляет трафик с порта 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 используется в ПРЯМОЙ цепочке, где весь трафик, отправляемый на мост docker0, обрабатывается правилами в цепочке DOCKER.

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

Теперь я хочу отфильтровать трафик, отправленный на порт 8080 (трафик на порт 9010 был обработан ПРЕДВАРИТЕЛЬНОЙ МАРШРУТИЗАЦИЕЙ, и теперь это трафик, отправленный на порт 8080), блокируя все IP-адреса, разрешая трафик с IP 192.168.1.142. IP-адрес контейнера, конечно, может быть добавлен к этим правилам для повышения детализации.

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

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

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

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

Я думаю, что добавление этой строки устранило бы вашу проблему :

*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