Поиск…


Вступление

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

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

Синтаксис

  • iptables -I DOCKER [RULE ...] [ACCEPT | DROP] // Чтобы добавить правило в верхнюю часть таблицы DOCKER
  • iptables -D DOCKER [RULE ...] [ACCEPT | DROP] // Чтобы удалить правило из таблицы DOCKER
  • ipset restore </etc/ipfriends.conf // Чтобы перенастроить ваш ipps- адрес ipset

параметры

параметры подробности
ext_if Ваш внешний интерфейс на хосте Docker.
XXX.XXX.XXX.XXX Необходимо указать конкретный IP-адрес, на который должен быть предоставлен доступ к контейнерам Docker.
YYY.YYY.YYY.YYY Еще один IP-адрес, на который должен быть предоставлен доступ к контейнерам Docker.
ipfriends Имя ipset, определяющее IP-адреса, позволило получить доступ к вашим контейнерам Docker.

замечания

Эта проблема

Настройка правил iptables для контейнеров Docker немного сложна. Сначала вы думаете, что «классические» правила брандмауэра должны делать трюк.

Например, предположим, что вы сконфигурировали контейнер nginx-proxy + несколько контейнеров-служб для предоставления через HTTPS некоторых персональных веб-сервисов. Затем такое правило должно предоставлять доступ к вашим веб-службам только для IP XXX.XXX.XXX.XXX.

$ iptables -A INPUT -i eth0 -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
$ iptables -P INPUT DROP

Это не сработает, ваши контейнеры все еще доступны для всех.

Действительно, контейнеры Docker не являются хост-услугами. Они полагаются на виртуальную сеть вашего хоста, а хост выступает в качестве шлюза для этой сети. Что касается шлюзов, маршрутизируемый трафик не обрабатывается таблицей INPUT, а таблицей FORWARD, что делает правило выше, чем неэффективным.

Но это еще не все. Фактически, демон Docker создает множество правил iptables, когда он начинает делать свою магию в отношении подключения к сети контейнеров. В частности, создается таблица DOCKER для обработки правил, касающихся контейнеров, путем пересылки трафика из таблицы FORWARD в эту новую таблицу.

$ iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:https
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:http

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Решение

Если вы проверяете официальную документацию ( https://docs.docker.com/v1.5/articles/networking/) , то предоставляется первое решение ограничить доступ контейнера Docker к одному конкретному IP- адресу .

$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

Действительно, добавление правила в верхней части таблицы DOCKER - хорошая идея. Это не мешает правилам, автоматически настроенным Docker, и это просто. Но два основных недостатка:

  • Во-первых, что, если вам нужно получить доступ с двух IP вместо одного? Здесь может быть принят только один IP-адрес src, другие будут исключены, чтобы предотвратить это.
  • Во-вторых, что делать, если вашему докере нужен доступ в Интернет? При этом ни один запрос не будет выполнен, так как только сервер 8.8.8.8 может ответить на них.
  • Наконец, что делать, если вы хотите добавить другие логики? Например, предоставить доступ любому пользователю к вашему веб-серверу, работающему по протоколу HTTP, но ограничивать все остальное конкретным IP-адресом.

Для первого наблюдения мы можем использовать ipset . Вместо того, чтобы разрешать один IP в приведенном выше правиле, мы разрешаем всем IP-адресам из предопределенного ipset. В качестве бонуса ipset можно обновить без необходимости переопределять правило iptable.

$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP

Для второго наблюдения это каноническая проблема для брандмауэров: если вам разрешено связаться с сервером через брандмауэр, тогда брандмауэр должен разрешить серверу отвечать на ваш запрос. Это можно сделать, разрешив пакеты, связанные с установленным соединением. Для докерной логики он дает:

$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Последнее наблюдение фокусируется на одной точке: правила iptables необходимы. В самом деле, дополнительная логика для ПРИНИМАНИЯ некоторых подключений (в том числе связанных с ESTABLISHED соединениями) должна быть помещена в верхнюю часть таблицы DOCKER до правила DROP, которое отрицает все остальные соединения, не соответствующие ipset.

Поскольку мы используем опцию -I iptable, которая вводит правила в верхней части таблицы, предыдущие правила iptables должны быть вставлены в обратном порядке:

// Drop rule for non matching IPs
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
// Then Accept rules for established connections
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT 
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 3rd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 2nd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 1st custom accept rule

Учитывая все это, вы можете теперь проверить примеры, иллюстрирующие эту конфигурацию.

Ограничить доступ к контейнерам Docker к набору IP-адресов

Во-первых, при необходимости установите ipset . Пожалуйста, обратитесь к вашему дистрибутиву, чтобы узнать, как это сделать. Например, вот команда для Debian-подобных дистрибутивов.

$ apt-get update
$ apt-get install ipset

Затем создайте файл конфигурации, чтобы определить ipset, содержащий IP-адреса, для которых вы хотите открыть доступ к своим контейнерам Docker.

$ vi /etc/ipfriends.conf
# Recreate the ipset if needed, and flush all entries
create -exist ipfriends hash:ip family inet hashsize 1024 maxelem 65536
flush
# Give access to specific ips
add ipfriends XXX.XXX.XXX.XXX
add ipfriends YYY.YYY.YYY.YYY

Загрузите этот ipset.

$ ipset restore < /etc/ipfriends.conf

Убедитесь, что ваш демон Docker запущен: при вводе следующей команды не следует выводить никаких ошибок.

$ docker ps

Вы готовы вставить свои правила iptables. Вы должны уважать заказ.

// All requests of src ips not matching the ones from ipset ipfriends will be dropped.
$ iptables -I DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
// Except for requests coming from a connection already established.
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

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

$ iptables -D DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
$ iptables -D DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Настройка доступа к ограничениям при запуске Docker-демона

Работа в процессе

Некоторые пользовательские правила iptables

Работа в процессе



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow