Общая информация
Публикация сетевых портов из docker-контейнеров в хост-систему работает через DNAT трафика на сетевой интерфейс контейнера с приложением. В связи с этим привычная многим фильтрация трафика в цепочке INPUT
для docker-контейнеров игнорируется, что может привести к несанкционированному доступу к приложениям извне.
Чтобы полностью контролировать доступ к серверу с приложениями в docker'е, необходимо фильтровать трафик также в цепочке FORWARD
, а точнее в ее дочерней цепочке DOCKER-USER
.
Пример
Применение приведённых в примере правил без адаптации к конкретному серверу может привести к недоступности сервисов
# DO NOT FORGET TO RESTART DOCKER AFTER APPLYING IPTABLES RULES *mangle :EXT-MANGLE - [0:0] -A EXT-MANGLE -m state --state RELATED,ESTABLISHED -j ACCEPT -A EXT-MANGLE -i lo -j ACCEPT # Docker traffic -A EXT-MANGLE -i docker0 -j ACCEPT -A EXT-MANGLE -i br-+ -j ACCEPT # ICMP -A EXT-MANGLE -p icmp -j ACCEPT # Latera GWs -A EXT-MANGLE -s 188.120.244.146 -j ACCEPT -A EXT-MANGLE -s 5.63.158.193 -j ACCEPT # HTTP(S) -A EXT-MANGLE -p tcp -m multiport --dports 80,443 -j ACCEPT -A EXT-MANGLE -j RETURN :PREROUTING ACCEPT [0:0] -A PREROUTING -j EXT-MANGLE -A PREROUTING -j MARK --set-xmark 0xffff :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] COMMIT *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] COMMIT *filter :INPUT ACCEPT [0:0] -A INPUT -m mark ! --mark 0xffff -j ACCEPT -A INPUT -j DROP :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :DOCKER-USER - [0:0] -A DOCKER-USER -m mark --mark 0xffff -j DROP -A DOCKER-USER -j RETURN COMMIT
В данном примере:
- Используется одна общая цепочка
EXT-MANGLE
в таблицеmangle
для фильтрации всего входящего трафика (для цепочекINPUT
иFORWARD
таблицыfilter
). ПравилаEXT-MANGLE
отрабатывают в рамках цепочкиPREROUTING
(до замены порта при DNAT'е в таблицеnat
). - В
EXT-MANGLE
перечисляются разрешающие правила с действием (целью)ACCEPT
, после которого обработка трафика вmangle.PREROUTING
прекращается. - Трафик, который не попал под действие
ACCEPT
вEXT-MANGLE
, помечается специальной отметкой. - «Помеченный» трафик фильтруется при обработке в цепочках
INPUT
иFORWARD
(в дочерней цепочкеDOCKER-USER
).
Рекомендации
Список правил iptables стоит вести в отдельном файле (например, в /etc/network/iptables.up.rules
) и загружать в систему до запуска docker'а.
Изменение правил необходимо выполнять в следующем порядке:
- Исправление правил в файле с правилами iptables;
- Остановка docker'а (это приведёт к остановке всех приложений, работающих на сервере!);
- Применение правил iptables;
- Запуск docker'а;
- Проверка работы и доступности приложений (за основу можно взять карту проверок работы биллинга после обновлений).
Остановка docker'а для применения правил требуется для переинициализации правил iptables по контейнерам. К сожалению, переинициализировать их без остановки всего docker'а невозможно (см. https://github.com/moby/moby/issues/12294).
Применять правила iptables рекомендуется с использованием утилиты iptables-apply (в случае если эта утилита не получит подтверждение наличия у вас доступа к серверу, изменения в правилах будут отменены). При возникновении ошибок некорректные правила необходимо удалить из файла с правилами iptables, чтобы они не применялись при перезагрузке сервера.
Не рекомендуется
- Применять правила iptables «на горячую». Это может привести к расхождению между файлом с правилами и реальным состоянием iptables, которое станет явно заметным после перезагрузки сервера.
- Сохранять все правила iptables при выключении сервера и восстанавливать их при включении. Это приводит к восстановлению неактуальных («мусорных») правил docker'а по уже несуществующим экземплярам контейнеров, а также может привести к потере новых правил, если сервер был перезагружен по питанию.