Docker на сегодняшний день является одним из наиболее популярных движков для запуска контейнеров. Запущенные контейнеры получают частные IP-адреса, на которые Docker автоматически перенаправляет входящие соединения по настроенным портам.
Однако, есть один плохо документированный пробел в безопасности: проброшенные в контейнеры порты необходимо защищать брандмауэром не так, как порты, прослушиваемые приложениями, запущенными непосредственно на хостовой системе. Как следствие, оболочки над iptables
, такие как ufw
и firewalld
, оказываются неэффективными и пропускают входящие соединения, которые они вроде бы настроены блокировать.
Этот пробел был заявлен как баг в Docker по меньшей мере 10 раз. Поскольку проблема возникает на стыке двух подсистем, однозначно классифицировать ее как баг в Docker было бы априори несправедливо, и есть пользователи, которые по этому поводу отправляли отчеты об ошибке не разработчикам Docker, а разработчикам firewalld
и других аналогичных программ для организации сетевого экрана.
Корень проблемы в том, что пакеты, перенаправляемые средствами iptables
в контейнер через DNAT
, проходят через цепочку FORWARD
, а не INPUT
, как того ожидают наивные пользователи, ufw
и firewalld
.
Разработчики Docker признали проблему своей и сейчас обсуждают отказ от использования iptables
-цели DNAT
для проброса портов в контейнеры. В качестве альтернативы предлагается IPVS
, поскольку обрабатываемые им пакеты проходят через цепочку INPUT
так, как они проходили бы для запущенных непосредственно на хосте приложений. Тем самым, ufw
и firewalld
станут работоспособны на системах с контейнерами.
Параллельно обсуждается небезопасное поведение по умолчанию, когда порт, проброшенный через -p 1234:1234
, оказывается доступным извне, тогда как в большинстве случаев пользователи имели в виду доступ только с локальной машины. Ситуацию усугубляет то, что в различных руководствах для портов, которые должны быть доступны только с локальной машины, используется небезопасный синтаксис -p 1234:1234
вместо безопасного -p 127.0.0.1:1234:1234
.
Поскольку изменение является потенциально ломающим совместимость, новое поведение будет доступно в одной из следующих версий Docker, но настройки по умолчанию будут изменены еще через несколько релизов.
>>> Подробности