Заблокировать доступ к контейнерам Docker из интернета

Ко мне иногда обращаются разработчики с просьбами заблокировать доступ к какому-нибудь контейнеру из интернета. Для тех, кто не знает, скажу, что Docker по-умолчанию поднимает свои контейнеры с доступом к ним отовсюду. Никаких ограничений нет и настроить их не очень просто без понимания работы docker и iptables.

Онлайн-курс по устройству компьютерных сетей

На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Docker облегчил работу современным разработчикам и усложнил жизнь админам. Если не умеете с ним работать, смотрите мою статью по установке docker на centos. Такая простая задача, как блокировка доступа к какому-то сервису с помощью iptables резко усложнилась. Например, есть у вас одиночный сервер, на нем работают несколько контейнеров docker. Iptables вы не настраивали вообще, своих правил нет.

Тем не менее, набор правил iptables на хосте будет примерно такой.

Правила iptables, созданные docker

Docker создает бриджи, свои цепочки, правила и т.д. Причем управляет всем этим динамически. Нельзя просто взять и настроить iptables, как это делаю я в своей статье с помощью скрипта. Такой подход уже не работает.

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

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

Докер создает отдельную цепочку DOCKER-USER. Она проверяется раньше основной динамической цепочки DOCKER. Если вы хотите настроить свои правила доступа к контейнерам, добавляйте их в цепочку DOCKER-USER. Сервис не будет их трогать и изменять при рестарте или изменениях в контейнерах. Подробнее об этом читайте в документации.

Допустим, у нас есть контейнер с postgresql, который забинден на порт хоста 5432. По-умолчанию, к нему будет доступ из интернета. Чтобы запретить доступ к контейнеру, необходимо применить следующее правило.

/sbin/iptables -I DOCKER-USER -i eth0 -p tcp --dport 5432 -j DROP

В данном примере eth0 - внешний интерфейс, который смотрит в интернет. Усложним задачу. Вам надо запретить доступ из интернета к контейнеру, но при этом разрешить доступ с определенных ip адресов. Нам нужно применить несколько правил и следить за тем, чтобы разрешающие правила были выше запрещающих. Это можно сделать обычной нумерацией правил.

/sbin/iptables -I DOCKER-USER 1 -i eth0 -p tcp --dport 5432 -s 1.2.3.4 -j ACCEPT
/sbin/iptables -I DOCKER-USER 2 -i eth0 -p tcp --dport 5432 -s 5.6.7.8 -j ACCEPT
/sbin/iptables -I DOCKER-USER 3 -i eth0 -p tcp --dport 5432 -j DROP

Мы разрешили доступ с ip 1.2.3.4 и 5.6.7.8, всем остальным запретили, причем разрешающие правила поставили выше.

Посмотреть список правил конкретной цепочки с нумерацией можно командой:

# iptables -L DOCKER-USER --line-numbers -v -n

Блокировка доступа к контейнеру docker

Если вам надо очистить конкретную цепочку с правилами, используйте команду.

/sbin/iptables -F DOCKER-USER

Если захотите заодно заблокировать посторонним людям доступ по ssh, добавьте следующие правила в цепочку INPUT.

/sbin/iptables -I INPUT 1 -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -I INPUT 2 -i eth0 -p tcp --dport 22 -s 1.2.3.4 -j ACCEPT
/sbin/iptables -I INPUT 3 -i eth0 -p tcp --dport 22 -s 5.6.7.8 -j ACCEPT
/sbin/iptables -I INPUT 4 -i eth0 -p tcp --dport 22 -j DROP

Я рекомендую не лениться и закрывать доступ посторонним ко всему, что им не нужно. Важно делать это в том числе на dev серверах. Эта статья в основном для них. Разработчики часто создают тестовые серверы и особо не следят за ними, хотя там могут быть продуктовые базы и прочая приватная информация. Iptables для них темный лес.

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

Я предложил простое и топорное решение в лоб. Данную задачу можно решить различными способами. Например, правила iptables можно настраивать сразу вместе с контейнером и применять их при запуске. Можно вообще отключить динамическое управление правилами со стороны docker и писать их все самостоятельно. Но это все требует больше времени на настройку.

Чтобы после ребута сервера правила автоматически применились, можно оформить их в простой bash скрипт и запускать его с помощью cron, используя в качестве расписания параметр @reboot. Нужно только учесть один момент. Cron будет запускать скрипт раньше, чем успеет стартануть докер и создать свои цепочки. Надо каким-то образом его подождать. Самый простой способ поставить sleep на 5-10 секунд в скрипте перед применением правил для DOCKER-USER.

Онлайн-курс по устройству компьютерных сетей.

На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.
Не понравилась статья и хочешь научить меня администрировать? Пожалуйста, я люблю учиться. Комментарии в твоем распоряжении. Расскажи, как сделать правильно!

Помогла статья? Подписывайся на telegram канал автора

Анонсы всех статей, плюс много другой полезной и интересной информации, которая не попадает на сайт.

Автор Zerox

Владимир, системный администратор, автор сайта. Люблю настраивать сервера, изучать что-то новое, делиться знаниями, писать интересные и полезные статьи. Открыт к диалогу и сотрудничеству. Если вам интересно узнать обо мне побольше, то можете послушать интервью. Запись на моем канале - https://t.me/srv_admin/425 или на сайте в контактах.

6 комментариев

  1. Привет
    Спасибо за статью.
    У меня есть выделенная машина на hetzner

    Я хочу разместить пару тройку контейнеров с базами данных + Airflow.
    Я бы хотел, чтобы доступ к этим ресурсам был возможен только через VPN Wiregurd (запущен будет тоже в контейнере на том же хосте) и , так как часть "сервисов" не имеют защиты а только basic авторизация что недостаточно
    Подскажите куда смотреть

    • Что вы подразумеваете под "выделенная машина на hetzner"? Это железный сервер?

      • Боюсь ошибиться в формулировках, в облаке ты арендуешь "машину" с голым линуксом ставишь все что хочешь

        hetzner.com cloud

        • Это виртуальная машина. Тут вариант у вас один - разбираться с локальной настройкой фаервола - iptables. Сразу могу сказать, что это будет непростая задача, если в этом не разбираетесь.

  2. Спасибо за статью!
    Подскажите как заблокировать доступ к портам докера из интернета, но при этом разрешить доступ локальным программам, установленным на машине, например nginx?

    • По умолчанию у них будет доступ. В примерах из статьи я явно указываю в правилах, с каких интерфейсов запросы будут блокироваться:

      /sbin/iptables -I DOCKER-USER -i eth0 -p tcp --dport 5432 -j DROP

      Тут будут блокироваться запросы через интерфейс eth0, в моем случае это внешний интерфейс. Локальные запросы будут проходить.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Нажимая кнопку "Отправить комментарий" Я даю согласие на обработку персональных данных.
Используешь Telegram? Подпишись на канал автора →
This is default text for notification bar