Введение
Это вторая часть серии статей Docker, в которой мы рассмотрим некоторые продвинутые концепции для защиты вашего контейнера docker и убедимся, что даже если ваш контейнер будет взломан, злоумышленник не сможет многого добиться.
Если вы пропустили первую часть серии, вы можете ознакомиться с ней здесь.
Безопасность Docker и факторы, влияющие на нее, можно разделить на две основные и важнейшие категории: Пространства имен и cgroups – термины, используемые для их описания.
Пространства имен, согласно сайту Docker, “обеспечивают изоляцию запущенных процессов (контейнеров), ограничивая их доступ к системным ресурсам, при этом запущенный процесс не знает об ограничениях”.
Пространства имен не были введены Docker.
На момент написания статьи они уже присутствовали как часть ядра Linux.
Вторая наиболее важная вещь, которую необходимо знать, – это cgroups.
Это функция ядра Linux, которая позволяет ограничить доступ процессов и контейнеров к определенным системным ресурсам, таким как CPU, RAM, IOPS и сетевое соединение.
🐳 Как защитить Docker в производственной среде?
Ограничение идентификаторов PID
PID – это количество процессов или потоков, созданных контейнером.
Колонка PIDS содержит общее количество процессов и потоков ядра, которые были созданы контейнером на предыдущем этапе.
Ядро Linux называет это “потоками”.
В качестве альтернативы для описания того же самого используются “легкий процесс” или “задание ядра”.
Наличие большого числа в колонке PIDS в сочетании со скромным количеством процессов (как сообщают ps или top) может указывать на то, что что-то внутри контейнера генерирует значительное количество потоков.
Если злоумышленник получит доступ к вашему контейнеру, он может покалечить его, съев все ресурсы сервера и остановив его.
Поэтому рекомендуется уменьшить количество процессов, которые могут быть порождены в системе.
Для начала давайте узнаем, как проверить максимальное количество PID, которые может породить контейнер.
Чтобы проверить текущие PID, вы можете узнать это, набрав в docker stats.
Давайте запустим контейнер docker в режиме detached .
В режиме detached контейнер запускается и работает в фоновом режиме.
Это означает, что вы запускаете контейнер и можете использовать консоль после запуска для выполнения других команд.
Противоположностью режима detached является режим foreground.
Это режим по умолчанию, когда опция -d не используется.
В этом режиме консоль, которую вы используете для выполнения docker run, будет подключена к стандартному вводу, выводу и ошибкам.
Это означает, что ваша консоль прикреплена к процессу контейнера.
Вы можете запустить docker в detached режиме, добавив дополнительный флаг d вместе с -it.
Как мы видим, система предоставляет нам идентификатор, e604fd2d5c4a19d9487de7c9e0456563247c54715f269ee29b10d73624d51d84.
Это не что иное, как каталог для нашего только что порожденного контейнера.
Содержимое этого каталога будет содержать важную информацию.
Вы заметите каталог pids.
Этот каталог будет содержать информацию о PID нашего только нового контейнера.
Наша директория – /sys/fs/cgroup/pids/docker/e60….1d84.
Посмотрев на содержимое, вы увидите кучу файлов, хранящихся в каталоге.
Файл pids.max содержит максимальное количество процессов, которые могут быть порождены в нашем контейнере docker.
Если вы посмотрите на содержимое файла pids.max, то увидите, что в нем содержится слово max.
🐳 Почему процессы в контейнерах Docker не должны запускаться от имени Root
Это означает, что в нашем контейнере может быть порождено любое количество процессов.
В зависимости от условий использования можно установить верхнюю границу на количество порождаемых PID.
Примечание: Здесь 825d55fb6340 – это идентификатор образа. Чтобы просмотреть идентификаторы образов, просто введите docker image ls
В приведенном выше примере мы установили максимальное ограничение на количество процессов, которые могут быть порождены, которое фактически равно 100.
В зависимости от вашего случая использования, вы можете установить его намного ниже или выше.
Давайте подтвердим это, посетив файл
/sys/fs/cgroup/pids/docker/08a1b005840b54bda92116ad810ea228ae32d558a6fc81491b5f6ba042244f7e/pids.max.
Как вы можете убедиться, максимальное количество pids стало 100.
Давайте сначала разберемся, что такое сокет
Сокет обычно обозначается IP-адресом и портом.
Чтобы взаимодействовать с веб-сайтом или интерфейсом, вам понадобится только сокет, который означает IP-адрес и порт, связанный с IP-адресом, на котором работает служба.
Затем вы можете отправить запрос(ы) в сокет и ожидать ответа.
Это обычно называют сокетом TCP.
Существует еще один сокет, называемый сокетом UNIX.
Эти сокеты обычно используются для межпроцессного взаимодействия (IPC) в пределах одного компьютера/системы.
Сокет Docker – это сокет UNIX.
Когда вы вводите команду docker, например, docker pull, run и т.д., за кулисами клиент docker взаимодействует с демоном docker через сокет UNIX для выполнения ваших команд.
Файл docker.sock находится в каталоге /var/run, и владельцем этого файла является root.
Важно, чтобы вы не изменяли права доступа к этому файлу, поскольку это может привести к тому, что злоумышленник получит доступ к базовой хост-системе.
Также не рекомендуется монтировать этот файл в только что созданный контейнер docker, поскольку злоумышленники могут воспользоваться им для получения доступа к базовой хост-системе.
Но почему файл /var/run/docker.sock должен быть смонтирован кем-либо на контейнере?
🐳 Как опросить сокет Docker с помощью curl
Если у вас есть несколько контейнеров, и вы хотите получить доступ/управлять всеми ими из другого контейнера docker, то вам нужно смонтировать этот файл в контейнер docker, из которого вы хотите управлять/получать доступ к остальным контейнерам docker.
Процесс монтирования заключается в добавлении тега -v, за которым следует то, что вы хотите смонтировать и куда вы хотите смонтировать.
Пример, -v /opt/important:/tmp
В этом примере мы смонтировали каталог /opt/important из хост-системы в каталог /tmp в контейнере docker.
🐳 Как защитить TCP-сокет Docker с помощью TLS
Поэтому, если вы встретите DockerFile со строкой, подобной приведенной ниже, вы можете быть уверены в том, что любой злоумышленник, имеющий доступ к контейнеру docker, сможет смонтировать файловую систему хоста и прочитать все конфиденциальные файлы.
🐳 Как просмотреть историю событий Docker
Заключение
Эта статья была посвящена практической стороне дела.
Мы получили представление о концепции идентификаторов процессов и о том, как можно ограничить к ним доступ.
Позже мы обнаружили, что монтирование файла docker.sock может привести к уязвимости безопасности в контейнере Docker.
Безопасность чрезвычайно важна в среде Docker.
Помимо того, что технологическая безопасность сложна, ее также трудно достичь.