Данная статья применима к:
- Astra Linux Special Edition РУСБ.10015-01 (очередное обновление 1.7) с установленным обновлением БЮЛЛЕТЕНЬ № 2023-1023SE17 (оперативное обновление 1.7.5)
Введение
В статье приводится пример создания инфраструктуры сетевой службы RabbitMQ (далее - служба), обрабатывающей потоки данных с разными классификационными метками с соблюдением изоляции потоков данных. В создаваемой инфраструктуре:
- Передаваемые по сети прикладные данные (сетевые пакеты, далее - данные) маркируются классификационными метками. Для примера предполагается, что используются метки безопасности 0:0:0:0, 1:0:0:0 и 2:0:0:0 (см. Работа docker в непривилегированном режиме с ненулевыми метками безопасности).
- Обработка данных для каждого значения классификационной метки выполняется отдельным экземпляром службы, работающим в непривилегированном docker-контейнере (см. Установка и администрирование Docker в Astra Linux 1.7). Docker-контейнер при этом имеет классификационную метку, равную классификационной метке обрабатываемых данных.
- Служба внутри каждого контейнера работает с нулевой меткой безопасности и использует стандартные настройки сетевых портов.
- Со стороны операционной системы для каждого контейнера назначается отдельный набор физических сетевых портов. Данные поступающие в эти порты средствами гипервизора docker перенаправляются в стандартные сетевые порты службы в контейнере.
- Приложения, работая с собственными метками безопасности, направляют данные в стандартные порты службы. Данные при этом помечены классификационными метками, с которыми работают приложения.
- Данные, поступающие на стандартные порты, средствами сетевого фильтра iptables на основании классификационных меток данных перенаправляются на физические порта контейнеров с соответствующими метками безопасности.
- Данные, поступающие на физические порты ОС, средствами гипервизора docker перенаправляются на стандартные порты службы в контейнере.
В примере в качестве исходного образа используется готовый образ Astra Linux Special Edition 1.7, доступный в docker-репозитории Astra Linux. Можно также использовать собственные образы, см. Создание Docker-образов Astra Linux.
Создание и запуск образов выполняется на одной машине.
Таблица перенаправления портов:
Стандартный сетевой порт для прикладного ПО | Метка безопасности сетевого пакета | Физический сетевой порт | Сетевой порт контейнера |
---|---|---|---|
5672 | 0:0:0:0 | 56000 | Контейнер 0:0:0:0, порт 5672 |
1:0:0:0 | 56010 | Контейнер 1:0:0:0, порт 5672 | |
2:0:0:0 | 56020 | Контейнер 2:0:0:0, порт 5672 | |
15672 | 0:0:0:0 | 56001 | Контейнер 0:0:0:0, порт 15672 |
1:0:0:0 | 56011 | Контейнер 1:0:0:0, порт 15672 | |
2:0:0:0 | 56021 | Контейнер 2:0:0:0, порт 15672 | |
25672 | 0:0:0:0 | 56002 | Контейнер 0:0:0:0, порт 25672 |
1:0:0:0 | 56012 | Контейнер 1:0:0:0, порт 25672 | |
2:0:0:0 | 56022 | Контейнер 2:0:0:0, порт 25672 |
Поясняющая схема (на примере порта 5672):
Установка пакетов
Установить пакеты:
Настройка
Далее предполагается, что текущий пользователь включен в группу docker и все действия выполняются от его имени без использования sudo (см. Установка и администрирование Docker в Astra Linux 1.7).
Создать служебного пользователя, от имени которого будут запускаться контейнеры:
sudo useradd -s /usr/sbin/nologin <имя_пользователя>Присвоить созданному пользователю диапазон классификационных меток, например:
sudo pdpl-user -l 0:3 -c 0:0 -i 0 <имя_пользователя>Разрешить запускать службы без входа в систему:
sudo loginctl enable-linger <имя_пользователя>Включить автоматический запуск служб rootless docker для используемых классификационных меток:
sudo systemctl enable rootless-docker@$(systemd-escape <имя_пользователя>@0:0:0:0)
sudo systemctl enable rootless-docker@$(systemd-escape <имя_пользователя>@1:0:0:0)
sudo systemctl enable rootless-docker@$(systemd-escape <имя_пользователя>@2:0:0:0)Перезагрузить систему:
sudo rebootПосле перезагрузки убедиться, что службы активны:
sudo systemctl is-active rootless-docker@$(systemd-escape <имя_пользователя>@0:0:0:0)
sudo systemctl is-active rootless-docker@$(systemd-escape <имя_пользователя>@1:0:0:0)
sudo systemctl is-active rootless-docker@$(systemd-escape <имя_пользователя>@2:0:0:0)
Загрузка исходного образа
Загрузить базовый образ из репозитория:
docker pull registry.astralinux.ru/library/alse:1.7.5Проверить загруженный образ:
docker image lsПример вывода команды:REPOSITORY TAG IMAGE ID CREATED SIZE registry.astralinux.ru/library/alse 1.7.5 83d2946f21f2 4 weeks ago 94.3MB
Создание образа службы
Образ службы создается из загруженного на предыдущем шаге исходного образа. В исходный образ вносятся следующие изменения:
- Устанавливается пакет rabbitmq-server.
- Включается плагин rabbit-management, обеспечивающий управление службой через web-интерфейс.
- Создается пустой файл /etc/rabbitmq/rabbitmq.conf. Используемый минимальный docker-образ Astra Linux Special Edition не поддерживает МРД и МКЦ, и файл /etc/rabbitmq/rabbitmq.conf создается для устранения предупреждений.
- Изменяются принятые по умолчанию имя и пароль администратора службы rabbitmq (имя guest и пароль guest). Для примера используются имя astra и пароль astra. Изменения записываются в файл /etc/rabbitmq/rabbitmq.conf. Побочным эффектом изменения имени администратора является разрешение доступа через web-интерфейс, что далее упрощает администрирование службы в docker-контейнере.
- Разрешается доступ к сетевым портами, используемым службой (опция EXPOSE). Полный список портов см. по ссылке https://www.rabbitmq.com/networking.html. Доступ открывается ко всем перечисленным в списке портам, далее в примере используется минимально необходимый набор.
- Добавляется команда, выполняемая при запуске контейнера (опция ENTRYPOINT /usr/sbin/rabbitmq-server) – запуск службы.
Для создания образа службы:
Создать файл dockerfile с указанием исходного образа и описанием вносимых в него изменений. Пример файла:
FROM registry.astralinux.ru/library/alse:1.7.5 RUN apt update && apt install -y rabbitmq-server && rabbitmq-plugins enable rabbitmq_management RUN mkdir -p /etc/parsec/ RUN touch /etc/parsec/privsock.conf RUN echo "default_user = astra" >> /etc/rabbitmq/rabbitmq.conf RUN echo "default_pass = astra" >> /etc/rabbitmq/rabbitmq.conf RUN cat /etc/rabbitmq/rabbitmq.conf # https://www.rabbitmq.com/networking.html EXPOSE 1883 EXPOSE 4369 EXPOSE 5551-5552 EXPOSE 5671-5672 EXPOSE 6000-6500 EXPOSE 8883 EXPOSE 15671-15672 EXPOSE 15674-15675 EXPOSE 15692 EXPOSE 25672 EXPOSE 35672-35682 EXPOSE 61613-61614 ENTRYPOINT /usr/sbin/rabbitmq-server
Выполнить команду:
docker build -t astra-rabbitmq:latest -f dockerfile .В результате выполнения команды будет создан образ с именем astra-rabbitmq:latest.Проверить список образов можно командой:
docker image lsПримерный вывод команды:REPOSITORY TAG IMAGE ID CREATED SIZE astra-rabbitmq latest bd6b882259b0 10 seconds ago 455MB registry.astralinux.ru/library/alse 1.7.5 83d2946f21f2 4 weeks ago 94.3MB
Запуск и проверка docker-контейнера
Запустить из созданного образа docker-контейнер службы командой:
Опции команды:
- -d — выполнение контейнера в фоновом режиме;
- -p — перенаправление сетевых портов. Указанные сетевые порты физического компьютера перенаправляются на порты docker-контейнера. Для упрощения примера используется минимальный набор портов, достаточный для первичной проверки работы;
- --n astra-rabbitmq — имя контейнера (astra-rabbitmq);
- astra-rabbitmq:latest — имя образа из которого запускается контейнер.
Для простейших проверок работоспособности контейнера можно выполнить следующие действия:
Убедиться, что сетевые порты перенаправлены:
sudo netstat -putln | grep docker-proxyДля проверки непривилегированного контейнера использовать команду:
tcp 0 0 0.0.0.0:5672 0.0.0.0:* LISTEN 8135/docker-proxy
tcp 0 0 0.0.0.0:25672 0.0.0.0:* LISTEN 8107/docker-proxy
tcp 0 0 0.0.0.0:15672 0.0.0.0:* LISTEN 8121/docker-proxysudo netstat -putln | grep rootlesskitУбедиться, что контейнер запущен:
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8bf47e60863a astra-rabbitmq:latest "/bin/sh -c /usr/sbi…" About a minute ago Up About a minute 1883/tcp, 4369/tcp, 5551-5552/tcp, 5671/tcp, 6000-6500/tcp, 8883/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 15674-15675/tcp, 0.0.0.0:15672->15672/tcp, 15692/tcp, 35672-35682/tcp, 61613-61614/tcp, 0.0.0.0:25672->25672/tcp astra-rabbitmqПодключиться к web-интерфейсу службы в контейнере (для входа использовать заданные ранее имя astra и пароль astra:
firefox http://127.0.0.1:15672/или, если пользовательская сессия не перезапускалась и переменным окружения не были присвоены значения:DISPLAY=:0 firefox http://127.0.0.1:15672/Выполнить в контейнере команду проверки текущего статуса службы:
docker exec astra-rabbitmq rabbitmqctl status
Экспорт образа для последующего использования
Экспортировать образ для последующего развертывания:
docker save astra-rabbitmq:latest -o astra-rabbitmq.tarЕсли предполагается далее загружать экспортированный образ от имени других пользователей, то предоставить доступ на чтение к созданному файлу и содержащему его каталогу. Предоставить доступ на чтение к файлу можно командой:
chmod +r astra-rabbitmq.tarПредоставить доступ на чтение к текущему каталогу можно командой:chmod +x `pwd`
Для предоставления доступа также можно использовать ACL (см. Списки управления доступом к файловым объектам (ACL) в Astra Linux).
Развертывание службы в docker-контейнерах
Установка пакетов
Для запуска службы в привилегированном контейнере достаточно установить пакет docker.io. Для запуска в непривилегированных контейнерах дополнительно требуется пакет rootless-helper-astra и пакет dbus-user-session. Для управления трафиком с разными классификационными метками требуются пакет iptables-astralabel-common и пакеты iptables-astralabel-*, соответствующие используемому ядру. Для тестирования можно использовать пакет netcat-openbsd. Команда для установки всех пакетов:
Отдельная служба в непривилегированном контейнере с нулевой классификационной меткой
Созданный и экспортированный ранее образ может быть импортирован в непривилегированное пользовательское окружения и запущен в этом окружении. Далее для примера все действия выполняются от имени текущего пользователя ($USER).
Запустить пользовательскую службу docker:
sudo systemctl start rootless-docker@$(systemd-escape $USER)Импортировать ранее выгруженный образ:
rootlessenv docker load -i astra-rabbitmq.tarПроверить список образов:
rootlessenv docker image lsЗапустить контейнер из импортированного образа:
rootlessenv docker run --restart always -d -p 5672:5672 -p 15672:15672 -p 25672:25672 --name astra-rabbitmq astra-rabbitmq:latest
Для проверки работы запущенного контейнера можно использовать указанные выше рекомендации, выполняя docker-команды в непривилегированном окружении: Запуск и проверка docker-контейнера.
Комплект служб, работающих в контейнерах с разными метками безопасности
Развертывание комплекта служб, работающих с разными метками безопасности, повторяет действия, описанные в предыдущем разделе. Отличия в том, что службы запускаются с разными метками безопасности и с разными наборами внешних сетевых портов. Предполагается, что службы запускаются от имени специально пользователя. Этот пользователь должен иметь разрешенный диапазон меток безопасности, включающий все метки безопасности запускаемых от его имени непривилегированных контейнеров. Для примера используется имя пользователя macuser с разрешенным диапазоном иерархических уровней конфиденциальности от нуля до трех . Создать такого пользователя можно следующим образом:
Создать пользователя:
sudo useradd macuserНазначить созданному пользователю диапазон допустимых иерархических уровней конфиденциальности:
sudo pdpl-user -l 0:3 macuserСоздать для пользователя системные службы непривилегированного docker, разрешить их автоматический запуск после перезагрузки. Для каждой используемой метки безопасности создается отдельная служба:
sudo systemctl enable rootless-docker@$(systemd-escape macuser@0:0:0:0)
sudo systemctl enable rootless-docker@$(systemd-escape macuser@1:0:0:0)
sudo systemctl enable rootless-docker@$(systemd-escape macuser@2:0:0:0)
sudo systemctl start rootless-docker@$(systemd-escape macuser@0:0:0:0)
sudo systemctl start rootless-docker@$(systemd-escape macuser@1:0:0:0)
sudo systemctl start rootless-docker@$(systemd-escape macuser@2:0:0:0)
Порядок действий по настройке и запуску комплекта служб:
Импортировать ранее экспортированный образ для каждой метки безопасности:
sudo pdp-exec -u macuser -l 0:0:0:0 -- rootlessenv docker load -i astra-rabbitmq.tar
sudo pdp-exec -u macuser -l 1:0:0:0 -- rootlessenv docker load -i astra-rabbitmq.tar
sudo pdp-exec -u macuser -l 2:0:0:0 -- rootlessenv docker load -i astra-rabbitmq.tarЗапустить из импортированных образов контейнеры. Для каждого контейнера задается индивидуальный набор внешних портов:
sudo pdp-exec -u macuser -l "0:0:0:0" -- rootlessenv docker run --restart always -d -p 56000:5672 -p 56001:15672 -p 56002:25672 --name astra-rabbitmq astra-rabbitmq:latest
sudo pdp-exec -u macuser -l "1:0:0:0" -- rootlessenv docker run --restart always -d -p 56010:5672 -p 56011:15672 -p 56012:25672 --name astra-rabbitmq astra-rabbitmq:latest
sudo pdp-exec -u macuser -l "2:0:0:0" -- rootlessenv docker run --restart always -d -p 56020:5672 -p 56021:15672 -p 56022:25672 --name astra-rabbitmq astra-rabbitmq:latestНастроить правила iptables для маршрутизации данных в зависимости от их классификационных меток. Правила настраиваются для каждой используемой классификационной метки (для каждого иерархического уровня конфиденциальности — 0, 1 и 2), а также отдельно для внешних интерфейсов (в примере - интерфейс eth0) для интерфейса локальной петли (127.0.0.1):
Для постоянного сохранения правил после перезагрузки см. Сохранение и восстановление правил iptables.sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 5672 -m astralabel --maclev 0 -j REDIRECT --to-port 56000
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 5672 -m astralabel --maclev 0 -j REDIRECT --to-port 56000
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 15672 -m astralabel --maclev 0 -j REDIRECT --to-port 56001
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 15672 -m astralabel --maclev 0 -j REDIRECT --to-port 56001
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25672 -m astralabel --maclev 0 -j REDIRECT --to-port 56002
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 25672 -m astralabel --maclev 0 -j REDIRECT --to-port 56002sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 5672 -m astralabel --maclev 1 -j REDIRECT --to-port 56010
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 5672 -m astralabel --maclev 1 -j REDIRECT --to-port 56010
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 15672 -m astralabel --maclev 1 -j REDIRECT --to-port 56011
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 15672 -m astralabel --maclev 1 -j REDIRECT --to-port 56011
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25672 -m astralabel --maclev 1 -j REDIRECT --to-port 56012
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 25672 -m astralabel --maclev 1 -j REDIRECT --to-port 56012sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 5672 -m astralabel --maclev 2 -j REDIRECT --to-port 56020
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 5672 -m astralabel --maclev 2 -j REDIRECT --to-port 56020
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 15672 -m astralabel --maclev 2 -j REDIRECT --to-port 56021
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 15672 -m astralabel --maclev 2 -j REDIRECT --to-port 56021
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25672 -m astralabel --maclev 2 -j REDIRECT --to-port 56022
sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 25672 -m astralabel --maclev 2 -j REDIRECT --to-port 56022