Ключевые особенности и преимущества

Пространство имён пользователей Linux во всех контейнерах

Благодаря Enhanced Container Isolation все пользовательские контейнеры используют Linuxuser-namespace для дополнительной изоляции. Это означает, что пользователь root в контейнере сопоставляется с непривилегированным пользователем виртуальной машины Docker Desktop Linux.

Например:

$ docker run -it --rm --name=first alpine
/ # cat /proc/self/uid_map
         0     100000      65536

Вывод 0 100000 65536 является сигнатурой пространства имён пользователей Linux. Это означает, что привилегированный пользователь (0) в контейнере сопоставляется с непривилегированным пользователем 100000 на виртуальной машине Docker Desktop Linux, и сопоставление распространяется на непрерывный диапазон 64000 идентификаторов пользователей. То же самое относится и к идентификаторам групп.

Каждый контейнер получает эксклюзивный множество сопоставлений, управляемых Sysbox. Например, если запущен второй контейнер, диапазон сопоставления будет другим:

$ docker run -it --rm --name=second alpine
/ # cat /proc/self/uid_map
         0     165536      65536

Напротив, без Enhanced Container Isolation корневой пользователь контейнера на самом деле является пользователем root на хосте (он же «настоящий root»), и это относится ко всем контейнерам:

$ docker run -it --rm alpine
/ # cat /proc/self/uid_map
         0       0     4294967295

Благодаря использованию пространства имён пользователей Linux расширенная изоляция контейнеров гарантирует, что процессы контейнера никогда не будут запускаться от имени пользователя с идентификатором 0 (истинный root) на виртуальной машине Linux. На самом деле они никогда не запускаются с действительным идентификатором пользователя на виртуальной машине Linux. Таким образом, их возможности Linux ограничены только ресурсами внутри контейнера, что значительно увеличивает изоляцию по сравнению с обычными контейнерами, как между контейнерами, так и между контейнерами.

Привилегированные контейнеры также защищены

Привилегированные контейнеры docker run --privileged ... небезопасны, поскольку они предоставляют контейнеру полный доступ к ядру Linux. Т. е. контейнер работает как настоящий root со всеми включенными возможностями, ограничения seccomp и AppArmor отключены, например, все аппаратные устройства выставлены.

Для организаций, которые хотят защитить Docker Desktop на компьютерах своих разработчиков, привилегированные контейнеры представляют проблему, поскольку они позволяют рабочим нагрузкам контейнера, как безопасным, так и вредоносным, получать контроль над ядром Linux внутри виртуальной машины Docker Desktop и, таким образом, изменять параметры, связанные с безопасностью, например управление доступом к реестру. и сетевые прокси.

С Enhanced Container Isolation привилегированные контейнеры больше не могут этого делать. Сочетание пространства имён пользователей Linux и других методов безопасности, используемых Sysbox, гарантирует, что процессы внутри привилегированного контейнера могут получать доступ только к ресурсам, назначенным контейнеру.

Примечание

Расширенная изоляция контейнеров не запрещает пользователям запускать привилегированные контейнеры, а обеспечивает их безопасный запуск, гарантируя, что они могут изменять только ресурсы, связанные с контейнером. Привилегированные рабочие нагрузки, которые изменяют глобальные настройки ядра, например загружают модуль ядра или изменяют настройки BPF, не будут работать должным образом, поскольку при попытке таких операций они получат сообщение об ошибке «Отказано в доступе».

Например, Enhanced Container Isolation гарантирует, что привилегированные контейнеры не смогут получает доступ к сетевым настройкам Docker Desktop на виртуальной машине Linux, настроенной с помощью фильтров пакетов Berkeley (BPF):

$ docker run --privileged djs55/bpftool map show
Error: can't get next map: Operation not permitted

Напротив, без Enhanced Container Isolation привилегированные контейнеры могут легко сделать это:

$ docker run --privileged djs55/bpftool map show
17: ringbuf  name blocked_packets  flags 0x0
        key 0B  value 0B  max_entries 16777216  memlock 0B
18: hash  name allowed_map  flags 0x0
        key 4B  value 4B  max_entries 10000  memlock 81920B
20: lpm_trie  name allowed_trie  flags 0x1
        key 8B  value 8B  max_entries 1024  memlock 16384B

Обратите внимание, что для некоторых расширенных рабочих нагрузок контейнеров требуются привилегированные контейнеры, например Docker-in-Docker, Kubernetes-in-Docker и т.д. Благодаря Enhanced Container Isolation вы по-прежнему можете запускать такие рабочие нагрузки, но делать это гораздо безопаснее, чем раньше.

Контейнеры не могут совместно использовать пространства имён с виртуальной машиной Linux

Когда расширенная изоляция контейнеров включена, контейнеры не могут совместно использовать пространства имён Linux с хостом (например, pid, сеть, uts и т. д.), поскольку это существенно нарушает изоляцию.

Например, не удается совместно использовать пространство имён pid:

$ docker run -it --rm --pid=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share namespaces [pid] with the host (because they use the linux user-namespace for isolation): unknown.

Точно так же не удается совместно использовать сетевое пространство имён:

docker run -it --rm --network=host alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: invalid or unsupported container spec: sysbox containers can't share a network namespace with the host (because they use the linux user-namespace for isolation): unknown.

Кроме того, флаг --userns=host, используемый для отключения пространства имён пользователя в контейнере, игнорируется:

$ docker run -it --rm --userns=host alpine
/ # cat /proc/self/uid_map
         0     100000      65536

Наконец, права на сборку Docker --network=host и Docker buildx (network.host, security.insecure) запрещены. Сборки, требующие этого, не будут работать должным образом.

Привязать ограничения монтирования

Когда расширенная изоляция контейнеров включена, пользователи Docker Desktop могут продолжать привязывать каталоги узлов монтирования к контейнерам в соответствии с настройками через Настройки > Ресурсы > Общий доступ к файлам, но им больше не разрешено привязывать монтирование произвольные каталоги виртуальных машин Linux в контейнеры.

Это не позволяет контейнерам изменять конфиденциальные файлы внутри виртуальной машины Docker Desktop Linux, файлы, которые могут содержать конфигурации для управления доступом к реестру, прокси-серверы, конфигурации механизма Docker и многое другое.

Например, следующая привязка файла конфигурации Docker Engine (/etc/docker/daemon.json внутри виртуальной машины Linux) к контейнеру ограничена и, следовательно, завершается ошибкой:

$ docker run -it --rm -v /etc/docker/daemon.json:/mnt/daemon.json alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: error in the container spec: can't mount /etc/docker/daemon.json because it's configured as a restricted host mount: unknown

Напротив, без Enhanced Container Isolation это монтирование работает и предоставляет контейнеру полный доступ для чтения и записи к конфигурации Docker Engine.

Конечно, привязка файлов хоста продолжает работать в обычном режиме. Например, если пользователь настроил Docker Desktop для общего доступа к файлам в своём каталоге $HOME, он может привязать его к контейнеру:

$ docker run -it --rm -v $HOME:/mnt alpine
/ #

Примечание

Усовершенствованная изоляция контейнеров не позволяет привязке монтировать сокет Docker (/var/run/docker.sock) в контейнер, т. к. это, по сути, предоставляет контроль контейнера над Docker, тем самым нарушая изоляцию контейнера. Контейнеры, которые полагаются на это, не будут работать с включенной Enhanced Container Isolation.

Проверка конфиденциальных системных вызовов

Ещё одна особенность Enhanced Container Isolation заключается в том, что она перехватывает и проверяет несколько высокочувствительных системных вызовов внутри контейнеров, таких как mount и umount. Это гарантирует, что процессы, имеющие возможности для выполнения данных системных вызовов, не смогут использовать их для взлома контейнера.

Например, контейнер с кодом CAP_SYS_ADMIN (необходимым для выполнения системного вызова mount) не может использовать эту возможность для изменения монтирования привязки только для чтения на монтирование для чтения и записи:

$ docker run -it --rm --cap-add SYS_ADMIN -v $HOME:/mnt:ro alpine
/ # mount -o remount,rw /mnt /mnt
mount: permission denied (are you root?)

Поскольку каталог $HOME был смонтирован в каталог контейнера /mnt как доступный только для чтения, его нельзя изменяет изнутри контейнера на чтение и запись, даже если процесс контейнера имеет возможность сделать это. Это гарантирует, что процессы контейнера не смогут использовать mount или umount для взлома корневой файловой системы контейнера.

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

/ # mkdir /root/tmpfs
/ # mount -t tmpfs tmpfs /root/tmpfs
/ # mount -o remount,ro /root/tmpfs /root/tmpfs

/ # findmnt | grep tmpfs
├─/root/tmpfs    tmpfs      tmpfs    ro,relatime,uid=100000,gid=100000

/ # mount -o remount,rw /root/tmpfs /root/tmpfs
/ # findmnt | grep tmpfs
├─/root/tmpfs    tmpfs      tmpfs    rw,relatime,uid=100000,gid=100000

Данная функция вместе с пространством имён пользователя гарантирует, что даже если процесс-контейнер имеет все возможности Linux, их нельзя использовать для взлома контейнера.

Наконец, Enhanced Container Isolation выполняет проверку системных вызовов таким образом, что в подавляющем большинстве случаев это не влияет на производительность контейнеров. Он перехватывает системные вызовы пути управления, которые редко используются в большинстве рабочих нагрузок контейнера, но системные вызовы пути данных не перехватываются.

Сопоставления идентификаторов пользователей файловой системы

Как упоминалось выше, Enhanced Container Isolation включает пространство имён пользователей Linux во всех контейнерах, и это гарантирует, что диапазон идентификаторов пользователей контейнера (0-> 64 КБ) сопоставляется с непривилегированным диапазоном «реальных» идентификаторов пользователей в виртуальной машине Docker Desktop Linux. (например, 100000->165535).

Кроме того, каждый контейнер получает эксклюзивный диапазон реальных идентификаторов пользователей в виртуальной машине Linux (например, контейнер 0 может быть сопоставлен с 100000-> 165535, контейнер 2 с 165536-> 231071, контейнер 3 с 231072-> 296607 и т. д. ). То же самое относится и к групповым идентификаторам. Кроме того, если контейнер остановлен и перезапущен, нет гарантии, что он получит то же сопоставление, что и раньше. Это по дизайну и дополнительно вызывает безопасность.

Однако описанное выше представляет собой проблему при монтировании томов Docker в контейнеры, поскольку файлы, записанные в такие тома, будут иметь реальные идентификаторы пользователя/группы и, следовательно, не будут доступны при запуске/остановке/перезапуске контейнера или между контейнерами из-за к другому реальному идентификатору пользователя/группы каждого контейнера.

Чтобы решить эту проблему, Sysbox использует «переназначение идентификатора пользователя файловой системы» с помощью функции монтирования с сопоставлением идентификатора ядра Linux (добавлена в 2021 году) или альтернативного модуля под названием shiftfs. Данные технологии сопоставляют доступ к файловой системе от реального идентификатора пользователя контейнера (например, диапазон 100000-> 165535) к диапазону (0-> 65535) внутри виртуальной машины Linux Docker Desktop. Таким образом, тома теперь можно монтировать или совместно использовать в контейнерах, даже если каждый контейнер использует эксклюзивный диапазон идентификаторов пользователей. Пользователям не нужно беспокоиться о реальных идентификаторах пользователей контейнера.

Обратите внимание, что хотя изменение идентификатора пользователя файловой системы может привести к тому, что контейнеры получат доступ к файлам Linux VM, смонтированным в контейнер с реальным идентификатором пользователя 0 (т.е. root), описанные выше ограничения на привязку монтирования гарантируют, что никакие чувствительные файлы Linux VM не могут быть смонтированы в контейнер.

Эмуляция Procfs и Sysfs

Ещё одна особенность Enhanced Container Isolation заключается в том, что внутри каждого контейнера частично эмулируются файловые системы procfs («/proc») и sysfs («/sys»). Это служит нескольким целям, таким как сокрытие конфиденциальной информации о хосте внутри контейнера и пространство имён ресурсов ядра хоста, которые ещё не распределены самим ядром Linux.

В качестве простого примера, когда включена Enhanced Container Isolation, файл /proc/uptime показывает время безотказной работы самого контейнера, а не виртуальной машины Docker Desktop Linux:

$ docker run -it --rm alpine
/ # cat /proc/uptime
5.86 5.86

Напротив, без Enhanced Container Isolation вы видите время безотказной работы виртуальной машины Docker Desktop Linux. Хотя это тривиальный пример, он показывает, как Enhanced Container Isolation направлена на предотвращение утечки конфигурации и информации виртуальной машины Linux в контейнер, чтобы затруднить взлом виртуальной машины.

Кроме того, внутри контейнера также эмулируются несколько других ресурсов в /proc/sys, которые не входят в пространство имён ядра Linux. Каждый контейнер видит отдельное представление каждого такого ресурса, и Sysbox согласовывает значения между контейнерами при программировании соответствующей настройки ядра Linux.

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