Данная статья применима к:

Введение

В статье приводится пример создания инфраструктуры сетевой службы RabbitMQ (далее - служба), обрабатывающей потоки данных с разными классификационными метками с соблюдением изоляции потоков данных. В создаваемой инфраструктуре:

  1. Передаваемые по сети прикладные данные (сетевые пакеты, далее - данные) маркируются классификационными метками. Для примера предполагается, что используются метки безопасности 0:0:0:0, 1:0:0:0 и 2:0:0:0 (см. Работа docker в непривилегированном режиме с ненулевыми метками безопасности).
  2. Обработка данных для каждого значения классификационной метки выполняется отдельным экземпляром службы, работающим в непривилегированном docker-контейнере (см. статью Установка и администрирование Docker в Astra Linux Special Edition). Docker-контейнер при этом имеет классификационную метку, равную классификационной метке обрабатываемых данных. 
  3. Служба внутри каждого контейнера работает с нулевой меткой безопасности и использует стандартные настройки сетевых портов.
  4. Со стороны операционной системы для каждого контейнера назначается отдельный набор физических сетевых портов. Данные поступающие в эти порты средствами гипервизора docker перенаправляются в стандартные сетевые порты службы в контейнере.
  5. Приложения, работая с собственными метками безопасности, направляют данные в стандартные порты службы. Данные при этом помечены классификационными метками, с которыми работают приложения.
  6. Данные, поступающие на стандартные порты, средствами сетевого фильтра iptables на основании классификационных меток данных перенаправляются на физические порта контейнеров с соответствующими метками безопасности.
  7. Данные, поступающие на физические порты ОС, средствами гипервизора docker перенаправляются  на стандартные порты службы в контейнере.

В примере в качестве исходного образа используется готовый образ Astra Linux Special Edition 1.7, доступный в docker-репозитории Astra Linux. Можно также использовать собственные образы, см. Создание Docker-образов Astra Linux.
Создание и запуск образов выполняется на одной машине.

Таблица перенаправления портов:

Стандартный сетевой порт
для прикладного ПО
Метка безопасности
сетевого пакета
Физический сетевой портСетевой порт контейнера
56720:0:0:056000Контейнер 0:0:0:0, порт 5672
1:0:0:056010Контейнер 1:0:0:0, порт 5672
2:0:0:056020Контейнер 2:0:0:0, порт 5672
156720:0:0:056001Контейнер 0:0:0:0, порт 15672
1:0:0:056011Контейнер 1:0:0:0, порт 15672
2:0:0:056021Контейнер 2:0:0:0, порт 15672
256720:0:0:056002Контейнер 0:0:0:0, порт 25672
1:0:0:056012Контейнер 1:0:0:0, порт 25672
2:0:0:056022Контейнер 2:0:0:0, порт 25672

Поясняющая схема (на примере порта 5672):

Установка пакетов для подготовки образов

Дальнейшие действия выполняются от имени пользователя с правами администратора (при включенном МРД - от имени пользователя с правами администратора и высоким уровнем целостности).

Для подготовки образов достаточно установить пакет docker.io:

sudo apt install -y docker.io
Комплект пакетов для запуска контейнеров см. далее: Установка пакетов для развертывания службы.

Настройка

Дальнейшие действия выполняются от имени пользователя с правами администратора (при включенном МРД - от имени пользователя с правами администратора и высоким уровнем целостности).

  1. Создать служебного пользователя, от имени которого будут запускаться контейнеры:

    sudo useradd -s /usr/sbin/nologin <имя_пользователя>

  2. Присвоить созданному пользователю диапазон классификационных меток, например:

    sudo pdpl-user -l 0:3 -c 0:0 -i 0 <имя_пользователя>

  3. Разрешить запускать службы без входа в систему:

    sudo loginctl enable-linger <имя_пользователя>

  4. Включить автоматический запуск служб 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)

  5. Перезагрузить систему:

    sudo reboot

  6. После перезагрузки убедиться, что службы активны:

    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 и, где это возможно, действия выполняются имени пользователя без использования sudo (см. Установка и администрирование Docker в Astra Linux 1.7). 

  1. Загрузить базовый образ из репозитория:

    docker pull registry.astralinux.ru/library/alse:1.7.5

  2. Проверить загруженный образ:

    docker image ls
    Пример вывода команды:

    REPOSITORY                            TAG       IMAGE ID       CREATED        SIZE
    registry.astralinux.ru/library/alse   1.7.5     83d2946f21f2   4 weeks ago    94.3MB
    

Создание образа службы

Образ службы создается из загруженного на предыдущем шаге исходного образа. В исходный образ вносятся следующие изменения:

  1. Устанавливается пакет rabbitmq-server.
  2. Включается плагин rabbit-management, обеспечивающий управление службой через web-интерфейс.
  3. Создается пустой файл /etc/rabbitmq/rabbitmq.conf. Используемый минимальный docker-образ Astra Linux Special Edition не поддерживает МРД и МКЦ, и файл /etc/rabbitmq/rabbitmq.conf создается для устранения предупреждений.
  4. Изменяются принятые по умолчанию имя и пароль администратора службы rabbitmq (имя guest и пароль guest). Для примера используются имя astra и пароль astra. Изменения записываются в файл /etc/rabbitmq/rabbitmq.conf. Побочным эффектом изменения имени администратора является разрешение доступа через web-интерфейс, что далее упрощает администрирование службы в docker-контейнере.
  5. Разрешается доступ к сетевым портами, используемым службой (опция EXPOSE). Полный список портов см. по ссылке https://www.rabbitmq.com/networking.html. Доступ открывается ко всем перечисленным в списке портам, далее в примере используется минимально необходимый набор.
  6. Добавляется команда, выполняемая при запуске контейнера (опция ENTRYPOINT /usr/sbin/rabbitmq-server) – запуск службы.

Для создания образа службы:

  1. Создать файл Dockerfile с указанием исходного образа и описанием вносимых в него изменений. Пример файла:

    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
  2. Выполнить команду:

    docker build -t astra-rabbitmq:latest -f Dockerfile .
    В результате выполнения команды будет создан образ с именем astra-rabbitmq:latest.

  3. Проверить список образов можно командой:

    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-контейнер службы командой:

docker run -d -p 5672:5672 -p 15672:15672 -p 25672:25672 --name astra-rabbitmq astra-rabbitmq:latest

Опции команды:

  • -d — выполнение контейнера в фоновом режиме;
  • -p — перенаправление сетевых портов. Указанные сетевые порты физического компьютера перенаправляются на порты docker-контейнера. Для упрощения примера используется минимальный набор портов, достаточный для первичной проверки работы;
  • --name astra-rabbitmq — имя контейнера (astra-rabbitmq);
  •  astra-rabbitmq:latest — имя образа из которого запускается контейнер.

Для простейших проверок работоспособности контейнера можно выполнить следующие действия:

  1. Убедиться, что сетевые порты перенаправлены:

    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-proxy   
    Для проверки непривилегированного контейнера использовать команду:
    sudo netstat -putln | grep rootlesskit

  2. Убедиться, что контейнер запущен:

    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

  3. Подключиться к web-интерфейсу службы в контейнере (для входа использовать заданные ранее имя astra и пароль astra:

    firefox http://127.0.0.1:15672/
    или, если пользовательская сессия не перезапускалась и переменным окружения не были присвоены значения:
    DISPLAY=:0 firefox http://127.0.0.1:15672/

  4. Выполнить в контейнере команду проверки текущего статуса службы:

    docker exec astra-rabbitmq rabbitmqctl status

Экспорт образа для последующего использования

  1. Экспортировать образ для последующего развертывания:

    docker save astra-rabbitmq:latest -o astra-rabbitmq.tar

  2. Если предполагается далее загружать экспортированный образ от имени других пользователей, то предоставить доступ на чтение к созданному файлу и содержащему его каталогу. Предоставить доступ на чтение к файлу можно командой:

    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. Команда для установки всех пакетов:

sudo apt install -y docker.io rootless-helper-astra iptables-astralabel-common iptables-astralabel-`uname -r` dbus-user-session netcat-openbsd

В примере пакет iptables-astralabel-* устанавливается для загруженного в момент установки ядра.

Отдельная служба в непривилегированном контейнере с нулевой классификационной меткой

Созданный и экспортированный ранее образ может быть импортирован в непривилегированное пользовательское окружение и запущен в этом окружении. Далее для примера действия выполняются от имени текущего пользователя ($USER).

  1. Запустить пользовательскую службу docker:

    sudo systemctl start rootless-docker@$(systemd-escape $USER)

  2. Импортировать ранее выгруженный образ:

    rootlessenv docker load -i astra-rabbitmq.tar

  3. Проверить список образов:

    rootlessenv docker image ls

  4. Запустить контейнер из импортированного образа:

    rootlessenv docker run --restart always -d -p 5672:5672 -p 15672:15672 -p 25672:25672 --name astra-rabbitmq astra-rabbitmq:latest

Для проверки работы запущенного контейнера можно использовать указанные выше рекомендации, выполняя docker-команды в непривилегированном окружении: Запуск и проверка docker-контейнера.

Комплект служб, работающих в контейнерах с разными метками безопасности

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

Порядок действий по настройке и запуску комплекта служб:

  1. Импортировать ранее экспортированный образ для каждой используемой метки безопасности:

    sudo pdp-exec -u <имя_пользователя> -l 0:0:0:0 -- rootlessenv docker load -i astra-rabbitmq.tar
    sudo pdp-exec -u <имя_пользователя> -l 1:0:0:0 -- rootlessenv docker load -i astra-rabbitmq.tar
    sudo pdp-exec -u <имя_пользователя> -l 2:0:0:0 -- rootlessenv docker load -i astra-rabbitmq.tar

  2. Запустить из импортированных образов контейнеры. Для каждого контейнера задается индивидуальный набор внешних портов:

    sudo pdp-exec -u <имя_пользователя> -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 <имя_пользователя> -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 <имя_пользователя> -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

  3. Настроить правила iptables для маршрутизации данных в зависимости от их классификационных меток. Правила настраиваются для каждой используемой классификационной метки (для каждого иерархического уровня конфиденциальности — 0, 1 и 2), а также отдельно для внешних интерфейсов (в примере - интерфейс eth0) для интерфейса локальной петли (127.0.0.1):

    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 56002

    sudo 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 56012

    sudo 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

    Для постоянного сохранения правил после перезагрузки см. Сохранение и восстановление правил iptables.

Тестирование структуры приложений RabbitMQ в docker-контейнерах

Для первичной проверки работоспособности контейнеров:

  1. Войти в сессию с ненулевой классификационной меткой.
  2. Выполнить команду:
    1. Для тестирования на локальном компьютере:

      nc 127.0.0.1 5672

    2. Для тестирования с удаленного компьютера:

      nc <IP-адрес_сервера_Rabbit_MQ> 5672
  3. Ввести текст:

    HELO
  4. Четыре раза нажать Enter.
  5. Если служба доступна и активна, то должен быть получен ответ:

    AMQP