Назад | Перейти на главную страницу

Почему docker один раз обходит правила ufw, а другой - нет?

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

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

Вот подробное описание того, что я сделал.

  1. Я хочу запретить весь входящий трафик:
sudo ufw default deny incoming
  1. Я хочу разрешить ssh:
sudo ufw allow ssh
  1. Я хочу разрешить все, что идет от моей хост-системы обратно к моей хост-системе через порт 8181 (Контекст: позже это будет использоваться для создания туннеля ssh к моему хосту и порту доступа. 8181 откуда угодно - но пока не важно)
sudo ufw allow from 127.0.0.1 to 127.0.0.1 port 8181
  1. Я включаю настройки брандмауэра:
sudo ufw enable

Если теперь я посмотрю на статус брандмауэра через sudo ufw status в нем говорится следующее:

Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere                  
127.0.0.1 8181             ALLOW       127.0.0.1                 
22/tcp (v6)                ALLOW       Anywhere (v6)

Мне кажется, это хорошо, но теперь самое странное. У меня есть API, который работает внутри docker контейнер доступен в порту 8080 внутренне.

Если я сейчас запустил контейнер докеров с помощью следующей команды и отобразил порт 8080 портировать 8181 в моей хост-системе

docker run -d --name ufw_test -p 8181:8080 mytest/web-app:latest

похоже, это обходит мое правило, которое я установил ранее, чтобы разрешать трафик только от 127.0.0.1 к 127.0.0.1 в порту 8181. Я мог получить доступ к своему API откуда угодно. Я пробовал это на разных ПК в одной сети, и мой API был доступен через 192.168.178.20:8181 с другого ПК. Я подумал, что способ исправить это - запустить мой контейнер следующим образом:

docker run -d --name ufw_test -p 127.0.0.1:8181:8080 mytest/web-app:latest

Это ограничило бы доступ к моему API так, как я предполагал, однако мне интересно, в чем причина того, что вторая команда сработала, а первая - нет?

ufw показывает только конфигурацию ufw и любые правила, вставленные непосредственно в конфигурацию вашего брандмауэра (с iptables напрямую или другим инструментом, таким как докер) без прохождения ufw НЕ отображаются.

Правила брандмауэра в Linux применяются в порядке их перечисления. Когда вы запускаете док-контейнер docker вставит правила, которые нужны вашим контейнерам докеров, перед существующими правилами и набор правил, который вы поддерживаете с помощью ufw.

Другими словами, Docker, открывающий порт, имеет приоритет над последующими правилами ufw, закрывающими конкретный порт.

Проверьте, например, с [sudo] iptables-save каков ваш эффективный набор правил.

Что касается почему -p 127.0.0.1:8181:8080 иначе работает?
Создаваемое докером правила брандмауэра по-прежнему будет иметь приоритет перед вашими правилами ufw, но вместо того, чтобы открывать порт на всех интерфейсах, в том числе для публики, вы теперь указываете докеру, что он будет гораздо более ограничительным и будет открывать порт только для localhost.