Изолируйте контейнеры с пространством имён пользователя
Пространства имён Linux обеспечивают изоляцию запущенных процессов, ограничивая их доступ к системным ресурсам, при этом работающий процесс не знает об ограничениях. Дополнительные сведения о пространствах имён Linux см. в статье Пространства имён Linux.
Лучший способ предотвратить атаки с повышением привилегий изнутри контейнера — настроить приложения вашего контейнера для запуска от имени непривилегированных пользователей. Для контейнеров, процессы которых должны выполняться от имени пользователя root
внутри контейнера, вы можете повторно сопоставить этого пользователя с менее привилегированным пользователем на хосте Docker. Сопоставленному пользователю назначается диапазон UID, которые функционируют в пространстве имён как обычные UID от 0 до 65536, но не имеют привилегий на самом хост-компьютере.
О переназначении и подчинении идентификаторов пользователей и групп
Само переназначение обрабатывается двумя файлами: /etc/subuid
и /etc/subgid
. Каждый файл работает одинаково, но один связан с диапазоном идентификаторов пользователей, а другой — с диапазоном идентификаторов групп. Рассмотрим следующую запись в /etc/subuid
:
testuser:231072:65536
Это означает, что testuser
назначается подчиненному диапазону идентификаторов пользователей из 231072
и следующих 65536 целых чисел в последовательности. UID 231072
отображается в пространстве имён (в данном случае внутри контейнера) как UID 0
(root
). UID 231073
отображается как UID 1
и так далее. Если процесс пытается повысить привилегии за пределами пространства имён, процесс выполняется как непривилегированный UID с большим числом на хосте, который даже не сопоставляется с реальным пользователем. Это означает, что процесс вообще не имеет привилегий в хост-системе.
Примечание
Несколько диапазонов
Можно назначить несколько подчиненных диапазонов для данного пользователя или группы, добавив несколько непересекающихся сопоставлений для одного и того же пользователя или группы в файле /etc/subuid
или /etc/subgid
. В этом случае Docker использует только первые пять сопоставлений в соответствии с ограничением ядра только пятью записями в /proc/self/uid_map
и /proc/self/gid_map
.
Когда вы настраиваете Docker для использования функции userns-remap
, вы можете дополнительно указывает существующего пользователя и/или группу или указывает default
. Если вы укажете default
, для этой цели будут созданы и использованы пользователь и группа dockremap
.
Предупреждение
Некоторые дистрибутивы, такие как RHEL и CentOS 7.3, не добавляют новую группу автоматически в файлы /etc/subuid
и /etc/subgid
. В этом случае вы несете ответственность за редактирование данных файлов и назначение непересекающихся диапазонов. Данный шаг описан в Предпосылки.
Очень важно, чтобы диапазоны не перекрывались, чтобы процесс не мог получает доступ к другому пространству имён. В большинстве дистрибутивов Linux системные утилиты управляют диапазонами для вас, когда вы добавляете или удаляете пользователей.
Это повторное сопоставление прозрачно для контейнера, но вносит некоторую сложность в настройку в ситуациях, когда контейнеру требуется доступ к ресурсам на хосте Docker, например, привязка монтирования к областям файловой системы, в которые системный пользователь не может записывать. С точки зрения безопасности лучше избегать таких ситуаций.
Предпосылки
Подчиненные диапазоны UID и GID должны быть связаны с существующим пользователем, даже если связь является деталью реализации. Пользователь владеет каталогами хранилища с пространством имён под номером
/var/lib/docker/
. Если вы не хотите использовать существующего пользователя, Docker может создать его для вас и использовать его. Если вы хотите использовать существующее имя пользователя или идентификатор пользователя, они уже должны существовать. Как правило, это означает, что соответствующие записи должны быть в/etc/passwd
и/etc/group
, но если вы используете другую серверную часть проверки подлинности, это требование может интерпретироваться иначе.Чтобы убедиться в этом, используйте команду
id
:$ id testuser uid=1001(testuser) gid=1001(testuser) groups=1001(testuser)
Способ переназначения пространства имён обрабатывается на хосте с использованием двух файлов,
/etc/subuid
и/etc/subgid
. Данные файлы обычно управляются автоматически при добавлении или удалении пользователей или групп, но в некоторых дистрибутивах, таких как RHEL и CentOS 7.3, вам может потребоваться управлять этими файлами вручную.Каждый файл содержит три поля: имя пользователя или идентификатор пользователя, за которым следует начальный UID или GID (который рассматривается как UID или GID 0 в пространстве имён) и максимальное количество UID или GID, доступных пользователю. Например, учитывая следующую запись:
testuser:231072:65536
Это означает, что процессы в пространстве имён пользователя, запущенные
testuser
, принадлежат хосту с UID231072
(который внутри пространства имён выглядит как UID0
) до 296607 (231072 + 65536 — 1). Данные диапазоны не должны перекрываться, чтобы гарантировать, что процессы с пространствами имён не смогут получает доступ к пространствам имён друг друга.После добавления пользователя проверяет
/etc/subuid
и/etc/subgid
, чтобы узнать, есть ли у вашего пользователя запись в каждом из них. Если нет, вам нужно добавить его, стараясь избежать дублирования.Если вы хотите использовать пользователя
dockremap
, автоматически созданного Docker, проверяет записьdockremap
в данных файлах после настройки и перезапуска Docker.Если на хосте Docker есть какие-либо места, где непривилегированный пользователь должен писать, соответствующим образом настраивает разрешения для данных мест. Это также верно, если вы хотите использовать пользователя
dockremap
, автоматически созданного Docker, но вы не можете изменяет разрешения до тех пор, пока не настроите и не перезапустите Docker.Включение
userns-remap
эффективно маскирует существующие слои образов и контейнеров, а также другие объекты Docker в пределах/var/lib/docker/
. Это связано с тем, что Docker необходимо настроить права собственности на данные ресурсы и фактически сохраняет их в подкаталоге в/var/lib/docker/
. Лучше всего включить эту функцию в новой установке Docker, а не в существующей.Точно так же, если вы отключает
userns-remap
, вы не сможете получает доступ ни к одному из ресурсов, созданных, пока он был включён.Проверяет известные ограничения пространства имён пользователей в пространствах имён пользователей, чтобы убедиться, что ваш опция использования возможен.
Включает userns-remap на демоне
Вы можете запускает dockerd
с флагом --userns-remap
или выполняет эту процедуру для настройки демона с помощью файла конфигурации daemon.json
. Рекомендуется метод daemon.json
. Если вы используете флаг, используйте следующую команду в качестве модели:
$ dockerd --userns-remap="testuser:testuser"
Отредактируйте
/etc/docker/daemon.json
. Предполагая, что файл ранее был пуст, следующая запись включаетuserns-remap
, используя пользователя и группу с именемtestuser
. Вы можете обращаться к пользователю и группе по идентификатору или имени. Вам нужно только указывает имя или идентификатор группы, если они отличаются от имени или идентификатора пользователя. Если вы указываете имя или идентификатор пользователя и группы, разделяет их двоеточием (:
). Все следующие форматы работают со значением, при условии, что UID и GIDtestuser
равны1001
:testuser
testuser:testuser
1001
1001:1001
testuser:1001
1001:testuser
{ "userns-remap": "testuser" }
Примечание
Чтобы использовать пользователя
dockremap
и позволить Docker создать его для вас, устанавливает значениеdefault
, а неtestuser
.Сохраняет файл и перезапустите Docker.
Если вы используете пользователя
dockremap
, убедиться, что Docker создал его с помощью командыid
.$ id dockremap uid=112(dockremap) gid=116(dockremap) groups=116(dockremap)
Убедиться, что запись добавлена в
/etc/subuid
и/etc/subgid
:$ grep dockremap /etc/subuid dockremap:231072:65536 $ grep dockremap /etc/subgid dockremap:231072:65536
Если данные записи отсутствуют, отредактируйте файлы как пользователя
root
и назначает начальный UID и GID, которые являются наивысшими назначенными, плюс смещение (в данном случае65536
). Будьте осторожны, чтобы не допустить перекрытия диапазонов.Убедиться, что предыдущие образы недоступны, с помощью команды
docker image ls
. Вывод должен быть пустым.Запускает контейнер из образа
hello-world
.$ docker run hello-world
Убедиться, что каталог с пространством имён существует в
/var/lib/docker/
с именем UID и GID пользователя в пространстве имён, принадлежит этому UID и GID и не может быть прочитан группой или всем миром. Некоторые из подкаталогов по-прежнему принадлежатroot
и имеют другие разрешения.$ sudo ls -ld /var/lib/docker/231072.231072/ drwx------ 11 231072 231072 11 Jun 21 21:19 /var/lib/docker/231072.231072/ $ sudo ls -l /var/lib/docker/231072.231072/ total 14 drwx------ 5 231072 231072 5 Jun 21 21:19 aufs drwx------ 3 231072 231072 3 Jun 21 21:21 containers drwx------ 3 root root 3 Jun 21 21:19 image drwxr-x--- 3 root root 3 Jun 21 21:19 network drwx------ 4 root root 4 Jun 21 21:19 plugins drwx------ 2 root root 2 Jun 21 21:19 swarm drwx------ 2 231072 231072 2 Jun 21 21:21 tmp drwx------ 2 root root 2 Jun 21 21:19 trust drwx------ 2 231072 231072 3 Jun 21 21:19 volumes
Ваш список каталогов может иметь некоторые отличия, особенно если вы используете другой драйвер контейнерного хранилища, чем
aufs
.Каталоги, принадлежащие переназначенному пользователю, используются вместо тех же каталогов непосредственно под
/var/lib/docker/
, а неиспользуемые версии (например,/var/lib/docker/tmp/
в приведённом здесь примере) могут быть удалены. Docker не использует их, пока включёнuserns-remap
.
Отключает переназначение пространства имён для контейнера
Если вы включаете пространства имён пользователей в демоне, все контейнеры запускаются с включенными по умолчанию пространствами имён пользователей. В некоторых ситуациях, например в привилегированных контейнерах, может потребоваться отключить пользовательские пространства имён для определённого контейнера. См. известные ограничения пространства имён пользователей для некоторых из данных ограничений.
Чтобы отключить пользовательские пространства имён для определённого контейнера, добавляет флаг --userns=host
в команду docker container create
, docker container run
или docker container exec
.
Существует побочный эффект при использовании этого флага: переназначение пользователя не будет включено для этого контейнера, но, поскольку уровни только для чтения (образа) являются общими для контейнеров, право собственности на файловую систему контейнеров все равно будет переназначено.
Это означает, что вся файловая система контейнера будет принадлежать пользователю, указанному в конфигурации демона --userns-remap
(231072
в приведённом выше примере). Это может привести к неожиданному поведению программ внутри контейнера. Например, sudo
(который проверяет, что его двоичные файлы принадлежат пользователю 0
) или двоичные файлы с флагом setuid
.
Известные ограничения пространства имён пользователей
Следующие стандартные функции Docker несовместимы с запуском демона Docker с включенными пространствами имён пользователей:
совместное использование пространств имён PID или NET с хостом (
--pid=host
или--network=host
).внешние драйверы (тома или хранилища), которые не знают или не могут использовать сопоставления пользователей демона.
Использование флага режима
--privileged
дляdocker run
без указания--userns=host
.
Пространства имён пользователей — это расширенная функция, требующая координации с другими возможностями. Например, если тома монтируются с хоста, владение файлом должно быть заранее согласовано с необходимостью чтения или записи содержимого тома.
В то время как пользователь root внутри процесса-контейнера с пространством имён пользователя имеет многие ожидаемые привилегии суперпользователя в контейнере, ядро Linux накладывает ограничения, основанные на внутреннем знании того, что это процесс с пространством имён пользователя. Одним заметным ограничением является невозможность использования команды mknod
. Отказано в разрешении на создание устройства в контейнере при запуске пользователем root
.