Docker. Изоляция контейнеров

Если вы когда-нибудь выполняли команду docker exec <образ> bash, то наверняка знаете, что контейнер изнутри очень похож на виртуальную машину. Если при наличии доступа к контейнеру через командную оболочку выполнить команду ps, то будут видны только работающие внутри него процессы. У контейнера свой сетевой стек и, на первый взгляд, собственная файловая система с корневым каталогом, никак не связанным с корневым каталогом хост-компьютера. Можно выполнять контейнеры с ограничением ресурсов, например объема оперативной памяти или доступных ресурсов CPU. Однако, как бы ни были похожи на первый взгляд эти два типа изоляции, важно отдавать себе отчет, что контейнеры — это не виртуальные машины. Lля контейнеров используются такие конструктивные элементы Linux, как пространства имен и chroot, а также контрольные группы.

Контрольные группы в Docker

Docker автоматически создает собственные контрольные группы всех типов. Просмотреть их список можно, выбрав каталоги docker в иерархии контрольных групп: ``` root@vagrant:/sys/fs/cgroup$ ls */docker | grep docker blkio/docker: cpuacct/docker:

Linux. Контрольные группы(cgroups)

Одним из главных «кирпичиков» создания контейнеров: контрольными группами (control groups, cgroups). Контрольные группы служат для ограничения доступных группе процессов ресурсов, например оперативной памяти, времени CPU и ресурсов сетевого ввода/вывода. С точки зрения безопасности хорошо настроенная контрольная группа позволяет гарантировать, что процесс не сможет влиять на поведение других процессов, захватывая все ресурсы — например, все ресурсы CPU или память, — не оставляя ничего остальным приложениям. Существует также контрольная группа pid, предназначенная для ограничения общего количества процессов в контрольной группе, тем самым сводя на нет результативность так называемой fork-бомбы. Fork-бомба — это программа, создающая процессы, которые, в свою очередь, тоже создают процессы, что приводит к экспоненциальному росту объема используемых ресурсов и в итоге выводит машину из строя.

Привилегии Linux

В ядре Linux существует более 30 привилегий. Они назначаются потокам выполнения и определяют, может ли данный поток производить некие действия. Например, чтобы выполнять привязку к какому-либо порту с номером меньше 1024, потоку требуется привилегия CAP_NET_BIND_SERVICE. Привилегия CAP_SYS_BOOT предназначена для того, чтобы указать, какие исполняемые файлы должны иметь право на перезагрузку системы. Для загрузки и выгрузки модулей ядра служит привилегия CAP_SYS_MODULE. Я уже упоминала ранее, что утилита ping выполняется от имени суперпользователя ровно столько времени, сколько ей нужно для того, чтобы предоставить себе привилегию на открытие потоком выполнения сетевого сокета прямого доступа, а именно привилегии CAP_NET_RAW. Подробную информацию о привилегиях можно получить на машине под управлением Linux с помощью команды man capabilities.

Docker. Безопасность контейнеров

А поскольку бит setuid — опасный путь к повышению полномочий, некоторые анализаторы образов контейнеров сообщают о наличии файлов с установленным битом setuid. Можно также запретить его использование, прибегнув к флагу --no-new-privileges команды docker run. По умолчанию контейнеры запускаются от имени суперпользователя. Это значит, запущенные в контейнерах приложения с намного большей вероятностью, чем в обычной машине под управлением Linux, будут выполняться от имени суперпользователя. Злоумышленнику, захватившему контроль над процессом внутри контейнера, конечно, все равно придется найти способ выйти за рамки контейнера, но затем он сразу получит права суперпользователя на хосте, не прибегая к какому-либо дальнейшему повышению полномочий. Но даже если контейнер запущен не от имени root, все равно остается возможность повысить полномочия на основе механизмов прав доступа Linux: