Общая информация
Публикация сетевых портов из docker-контейнеров в хост-систему по умолчанию работает через DNAT трафика на сетевой интерфейс контейнера с приложением. В связи с этим привычная многим фильтрация трафика в цепочке INPUT
для docker-контейнеров не применяется, что может привести к несанкционированному доступу к приложениям извне.
Чтобы полностью контролировать доступ к серверу с приложениями в docker'е, необходимо фильтровать трафик также в цепочке FORWARD
, а точнее в ее дочерней цепочке DOCKER-USER
.
Пример
Применение приведённых в примере правил без адаптации к конкретному серверу может привести к недоступности сервисов
# DO NOT FORGET TO RESTART DOCKER ENGINE AFTER APPLYING IPTABLES RULES *mangle :PREROUTING ACCEPT [0:0] :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 state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p icmp -j ACCEPT # Docker traffic -A INPUT -i docker0 -j ACCEPT -A INPUT -i br-+ -j ACCEPT # Latera GWs -A INPUT -s 188.120.244.146 -j ACCEPT -A INPUT -s 5.63.158.193 -j ACCEPT -A INPUT -j DROP :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :DOCKER-USER - [0:0] -A DOCKER-USER -m state --state RELATED,ESTABLISHED -j RETURN # Docker traffic -A DOCKER-USER -i docker0 -j RETURN -A DOCKER-USER -i br-+ -j RETURN # Latera GWs -A DOCKER-USER -s 188.120.244.146 -j RETURN -A DOCKER-USER -s 5.63.158.193 -j RETURN # Allow port only for one external address -A DOCKER-USER -s 192.168.1.5 -p tcp -m conntrack --ctorigdstport 3001 --ctdir ORIGINAL -j RETURN -A DOCKER-USER -p tcp -m conntrack --ctorigdstport 3001 --ctdir ORIGINAL -j DROP # HTTP(S) -A DOCKER-USER -p tcp -m conntrack --ctdir ORIGINAL --ctorigdstport 80 -j RETURN -A DOCKER-USER -p tcp -m conntrack --ctdir ORIGINAL --ctorigdstport 443 -j RETURN -A DOCKER-USER -j DROP COMMIT
В данном примере:
- Доступ к docker-контейнерам фильтруется в цепочке
DOCKER-USER
, а доступ к приложениям хост-системы — традиционно в цепочкеINPUT
. - Для разрешающих правил цепочки
DOCKER-USER
применяется действиеRETURN
, потому что трафик дальше продолжает обрабатываться служебными правилами Docker Engine. - Порты назначения в
DOCKER-USER
определяются с помощью модуляconntrack
, поскольку на данном этапе пакеты уже прошли через DNAT и порт назначения изменился на порт внутри контейнера.
Рекомендации
Список правил iptables стоит вести в отдельном файле (например, в /etc/network/iptables.up.rules
для Debian или в /etc/sysconfig/iptables
для Oracle Linux) и загружать в систему до запуска Docker Engine.
Изменение правил необходимо выполнять в следующем порядке:
- Изменить файл с правилами iptables;
- Остановить Docker Engine (команда: sudo systemctl stop docker, это приведёт к остановке всех docker-приложений, работающих на сервере);
- Применить правила iptables;
- Запустить Docker Engine (команда: sudo systemctl start docker)
- Проверить работу и доступность docker-приложений (за основу можно взять карту проверок работы биллинга после обновлений).
Остановка Docker Engine для применения правил требуется для переинициализации правил iptables по контейнерам. К сожалению, переинициализировать их без остановки всего Docker Engine невозможно (см. https://github.com/moby/moby/issues/12294).
Применять правила iptables в Debian Linux рекомендуется с использованием утилиты iptables-apply (в случае если эта утилита не получит подтверждения доступа к серверу, изменения в правилах будут отменены). При возникновении ошибок некорректные правила необходимо удалить из файла с правилами iptables, чтобы они не применялись при перезагрузке сервера.
Не рекомендуется
- Применять правила iptables «на горячую». Это может привести к расхождению между файлом с правилами и реальным состоянием iptables, которое станет явно заметным после перезагрузки сервера.
- Сохранять все правила iptables при выключении сервера и восстанавливать их при включении. Это приводит к восстановлению неактуальных («мусорных») правил docker'а по уже несуществующим экземплярам контейнеров, а также может привести к потере новых правил, если сервер был перезагружен по питанию.