Вопрос или проблема
У нас есть множество приложений, которые работают на Linux-сервере с использованием Docker.
В качестве примера, предположим, что мое приложение работает на ServerA как контейнер (Docker).
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
df68695a00f1 app/myapp:latest "/run.sh" 2 недели назад Запущен 2 дня 0.0.0.0:50423->3000/tcp reallymyapp
Приложение слушает на порту 50423 на хосте (сопоставлено с портом 3000 на контейнере).
DNS (конечная точка), который используется для доступа к приложению, указывает на хост HAProxy (скажем, ServerB), который маршрутизирует трафик на ServerA:50423.
На данный момент все работает хорошо.
Команда безопасности в нашей организации подняла вопрос о том, что все внешние IP-адреса потенциально могут подключаться к таким Docker-хостам (таким как ServerA), и они хотят, чтобы мы ограничили трафик, разрешив только определенному IP (ServerB, который является балансировщиком нагрузки) доступ к контейнерам и наоборот (ServerA к ServerB). Мы тогда будем разрешать подключение только от машин наших пользователей к ServerB/балансировщику нагрузки.
Теперь я следовал документации Docker и пытался вставить следующее правило, используя iptables в цепочку DOCKER-USER:
iptables -I DOCKER-USER -i ekf192 -s 10.1.2.10, 10.1.2.11, 10.1.2.12 -j ACCEPT
iptables -I DOCKER-USER -i ekf192 -j DROP
ACCEPT all -- 10.1.2.10 anywhere
ACCEPT all -- 10.1.2.11 anywhere
ACCEPT all -- 10.1.2.12 anywhere
LOG all -- anywhere anywhere LOG level info prefix "IPTables Dropped: "
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Обратите внимание, что нам нужен как входящий, так и исходящий трафик от/к этим хостам (10.1.2.10, 10.1.2.11, 10.1.2.12).
Теперь, согласно моим (ограниченным) знаниям о iptables, эти правила должны отклонять все входящие запросы, кроме тех, что исходят из указанных IP-адресов и наоборот, т.е. разрешать исходящий трафик к указанным IP.
Входящий трафик работает как ожидается, но исходящий трафик к этим ХОСТАМ отклоняется.
Я ломаю над этим голову и не могу понять, что идет не так… и не говоря уже о том, что я абсолютно плохо понимаю, как работают правила iptables.
Jan 12 16:24:43 sms100394 kernel: IPTables Dropped: IN=docker0 OUT=ekf192 MAC=02:42:09:37:a0:14:02:42:ac:11:00:02:08:00 SRC=172.17.0.2 DST=10.1.2.10 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=40235 DF PROTO=TCP SPT=3000 DPT=42579 WINDOW=242 RES=0x00 ACK FIN URGP=0
Jan 12 16:24:44 sms100394 kernel: IPTables Dropped: IN=docker0 OUT=ekf192 MAC=02:42:09:37:a0:14:02:42:ac:11:00:02:08:00 SRC=172.17.0.2 DST=10.1.2.11 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=3000 DPT=45182 WINDOW=29200 RES=0x00 ACK SYN URGP=0
Jan 12 16:24:45 sms100394 kernel: IPTables Dropped: IN=docker0 OUT=ekf192 MAC=02:42:09:37:a0:14:02:42:ac:11:00:02:08:00 SRC=172.17.0.2 DST=10.1.2.12 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=3000 DPT=45182 WINDOW=29200 RES=0x00 ACK SYN URGP=0
iptables по умолчанию не знает о “потоках”, только о отдельных пакетах. Поэтому для исходящих пакетов нужно добавить отдельное правило, что-то вроде:
iptables -I DOCKER-USER -i ekf192 -d 10.1.2.10, 10.1.2.11, 10.1.2.12
Ответ или решение
Ограничение входящего и исходящего трафика в Docker с использованием iptables
Ваша задача заключается в ограничении доступа к контейнерам Docker на сервере ServerA так, чтобы к ним могли подключаться только определенные IP-адреса, а также обеспечить правильный исходящий трафик от контейнеров к этим адресам. Для решения этой проблемы мы используем механизм фильтрации iptables, однако в вашей текущей реализации есть некоторые недоразумения, которые необходимо прояснить.
Исходная ситуация
У вас есть контейнер, который слушает на порту 50423 на хосте, перенаправляя трафик на порт 3000 внутри контейнера. Вы хотите ограничить доступ к этому контейнеру так, чтобы только ServerB (где расположен HAProxy) мог взаимодействовать с ServerA. Ваша команда безопасности хочет обеспечить, чтобы только определенные IP (в вашем случае 10.1.2.10, 10.1.2.11, и 10.1.2.12) имели доступ к вашим контейнерам, а также чтобы контейнеры могли отправлять трафик обратно на эти IP-адреса.
Проблема с правилами iptables
Ваши текущие правила iptables выглядят следующим образом:
iptables -I DOCKER-USER -i ekf192 -s 10.1.2.10,10.1.2.11,10.1.2.12 -j ACCEPT
iptables -I DOCKER-USER -i ekf192 -j DROP
Вы правильно разрешили входящий трафик от указанных IP, но проблема заключается в том, что ваши правила не учитывают исходящий трафик от контейнера к этим IP. В IPTables каждому из направлений (входящие и исходящие) могут быть заданы разные правила.
Согласно вашим логам видно, что исходящий трафик от контейнера 172.17.0.2 на указанные IP адреса (например, 10.1.2.10) блокируется. Это происходит, потому что вы не предоставили соответствующие правила для разрешения исходящего трафика.
Решение проблемы
Для решения проблемы с блокировкой исходящего трафика, вам необходимо добавить правила, которые будут разрешать этот трафик. Можете использовать следующее правило:
iptables -I DOCKER-USER -o ekf192 -d 10.1.2.10/32 -j ACCEPT
iptables -I DOCKER-USER -o ekf192 -d 10.1.2.11/32 -j ACCEPT
iptables -I DOCKER-USER -o ekf192 -d 10.1.2.12/32 -j ACCEPT
Таким образом, эти правила позволят контейнерам отправлять пакеты на указанные IP-адреса.
Полный набор правил iptables
Полный набор правил iptables для вашей ситуации может выглядеть следующим образом:
# Разрешаем входящий трафик от указанных IP
iptables -I DOCKER-USER -i ekf192 -s 10.1.2.10/32 -j ACCEPT
iptables -I DOCKER-USER -i ekf192 -s 10.1.2.11/32 -j ACCEPT
iptables -I DOCKER-USER -i ekf192 -s 10.1.2.12/32 -j ACCEPT
# Блокируем входящий трафик от всех остальных
iptables -I DOCKER-USER -i ekf192 -j DROP
# Разрешаем исходящий трафик к указанным IP
iptables -I DOCKER-USER -o ekf192 -d 10.1.2.10/32 -j ACCEPT
iptables -I DOCKER-USER -o ekf192 -d 10.1.2.11/32 -j ACCEPT
iptables -I DOCKER-USER -o ekf192 -d 10.1.2.12/32 -j ACCEPT
Подведение итогов
Итак, для сопоставления входящего и исходящего трафика вам необходимо отдельно разрешать оба типа соединений между Docker-контейнерами и вашими защищенными IP-адресами. Убедитесь, что вы протестировали новые правила, чтобы гарантировать, что блокировка и разрешение работают корректно в обоих направлениях. Теперь ваше окружение становится более безопасным, и ваша команда безопасности должна быть удовлетворена.