
Минимальный межсетевой экран на базе unikernel для QubesOS, который фильтрует сетевой трафик, реализует NAT и взаимодействует через Qubes DB и qrexec.
Уникернел, который может работать как ProxyVM в QubesOS, заменяя sys-firewall.
Для реализации протоколов Qubes используется библиотека mirage-qubes.
Подробности см. в статье A Unikernel Firewall for QubesOS.
Готовые бинарные файлы доступны на [странице релизов][]. Инструкции по установке см. в разделе Развёртывание ниже.
Примечание: самый надёжный способ сборки — с использованием Docker или Podman. Для этого хорошо подходит Fedora 42, Debian 12 тоже работает, но вам нужно будет следовать инструкциям на docker.com, чтобы получить Docker (не используйте версию из Debian).
Создайте новую AppVM Fedora-42 (или используйте существующую). В настройках Qube (Basic / Disk storage) увеличьте максимальный размер приватного хранилища с значения по умолчанию 2048 МиБ до 8192 МиБ. Откройте терминал.
Клонируйте этот Git-репозиторий и запустите скрипт build-with.sh с аргументом docker или podman (Примечание: вызов chcon обязателен на Fedora с новыми политиками SELinux, которые не позволяют стандартно хранить образы docker в домашнем каталоге):
mkdir /home/user/docker
sudo ln -s /home/user/docker /var/lib/docker
sudo chcon -Rt container_file_t /home/user/docker
sudo dnf install docker
sudo systemctl start docker
git clone https://github.com/mirage/qubes-mirage-firewall.git
cd qubes-mirage-firewall
sudo ./build-with.sh docker
Или
sudo systemctl start podman
git clone https://github.com/mirage/qubes-mirage-firewall.git
cd qubes-mirage-firewall
./build-with.sh podman
На моём ноутбуке это заняло около 15 минут (при повторном запуске будет гораздо быстрее). Шаг с символьной ссылкой в начале не нужен, если ваша сборочная VM является standalone. Он даёт Docker больше дискового пространства и позволяет не терять кэш образов Docker при перезагрузке Qube. Для Podman это не требуется, так как контейнеры по умолчанию хранятся в вашем домашнем каталоге.
Примечание: объектные файлы хранятся в каталоге _build для ускорения инкрементальной сборки.
Если вы меняете зависимости, вам нужно будет удалить этот каталог перед повторной сборкой.
Можно устанавливать пакет Docker или Podman в шаблонную VM, если вы хотите, чтобы он сохранялся после перезагрузки, но сама сборка межсетевого экрана должна выполняться в обычной AppVM.
Вы также можете собрать без этого скрипта, как и любой обычный уникернел Mirage; подробности см. в инструкциях по установке Mirage.
Скрипт сборки фиксирует версии используемых библиотек, гарантируя, что вы получите ровно тот же бинарный файл, что и в релизе. Если вы собираете без него, сборка будет выполняться с использованием последних версий (и хэш, вероятно, не совпадёт). Однако работать всё равно должно нормально.
Если вы хотите развернуть вручную, вам нужно просто скачать qubes-firewall.xen и
qubes-firewall.sha256 в domU и проверить, что файл .xen имеет соответствующий
хэш. qubes-firewall.xen — это сам уникернел, его следует скопировать в
vmlinuz в каталог /var/lib/qubes/vm-kernels/mirage-firewall в dom0, например
(если dev — это AppVM, где вы выполнили сборку):
[tal@dom0 ~]$ mkdir -p /var/lib/qubes/vm-kernels/mirage-firewall/
[tal@dom0 ~]$ cd /var/lib/qubes/vm-kernels/mirage-firewall/
[tal@dom0 mirage-firewall]$ qvm-run -p dev 'cat mirage-firewall/qubes-firewall.xen' > vmlinuz
Выполните эту команду в dom0, чтобы создать VM mirage-firewall, используя добавленное выше ядро mirage-firewall:
qvm-create \
--property kernel=mirage-firewall \
--property kernelopts='' \
--property memory=32 \
--property maxmem=32 \
--property netvm=sys-net \
--property provides_network=True \
--property vcpus=1 \
--property virt_mode=pvh \
--property audiovm='' \
--label=green \
--class StandaloneVM \
mirage-firewall
qvm-features mirage-firewall qubes-firewall 1
qvm-features mirage-firewall no-default-kernelopts 1
qvm-features mirage-firewall skip-update 1
Если вы знакомы с запуском salt-состояний в Qubes, вы также можете использовать скрипт SaltScriptToDownloadAndInstallMirageFirewallInQubes.sls для автоматического развёртывания последней версии mirage firewall в вашей Qubes OS. Введение можно найти здесь и здесь. Следуя инструкциям из первой ссылки, вы можете запустить скрипт в dom0 командой sudo qubesctl --show-output state.apply SaltScriptToDownloadAndInstallMirageFirewallInQubes saltenv=user. Скрипт проверяет контрольную сумму с интеграционного сервера и сравнивает её с последней версией, указанной в релизах GitHub. Возможно, потребуется изменить шаблоны VM в скрипте, которые используются для загрузки уникернела mirage, если в ваших шаблонах по умолчанию не установлены инструменты curl и tar. Также не забудьте изменить VM, в которых должен использоваться уникернел, или настроить «Qubes Global Settings».
Чтобы обновиться с более раннего выпуска, просто перезапишите /var/lib/qubes/vm-kernels/mirage-firewall/vmlinuz новой версией и перезапустите VM межсетевого экрана.
Вы можете запускать mirage-firewall вместе с существующим sys-firewall и выбирать, какие AppVM будут использовать какой межсетевой экран, через графический интерфейс.
Чтобы настроить AppVM на его использование, перейдите в настройки app VM в GUI и измените её NetVM с default (sys-firewall) на mirage-firewall.
Вы также можете настроить это, выполнив следующую команду в dom0 (замените my-app-vm на имя AppVM):
qvm-prefs --set my-app-vm netvm mirage-firewall
Кроме того, вы можете настроить mirage-firewall как вашу VM межсетевого экрана по умолчанию.
Обратите внимание, что по умолчанию dom0 использует sys-firewall в качестве своей «UpdateVM» (прокси для загрузки обновлений). mirage-firewall не может использоваться для этой цели, но подойдёт любая Linux VM. https://www.qubes-os.org/doc/software-update-dom0/ сообщает:
Роль UpdateVM может быть назначена любой VM в Qubes VM Manager, и в этом выборе нет существенных последствий для безопасности. По умолчанию эта роль назначена firewallvm.
OpenBSD в настоящее время не может использоваться в качестве netvm, поэтому если вы хотите использовать BSD в качестве вашей sys-net VM, вам нужно будет установить для неё netvm значение qubes-mirage-firewall (см. https://github.com/mirage/qubes-mirage-firewall/issues/146 для получения дополнительной информации).
Это означает, что у вас будет AppVMs -> qubes-mirage-firewall <- OpenBSD, где стрелка обозначает настройку свойства netvm.
В этом случае вам нужно будет указать qubes-mirage-firewall, какой клиент AppVM следует использовать в качестве аплинка:
qvm-prefs --set mirage-firewall -- kernelopts '--ipv4=X.X.X.X --ipv4-gw=Y.Y.Y.Y'
где X.X.X.X — IP-адрес для mirage-firewall, а Y.Y.Y.Y — IP-адрес вашей OpenBSD HVM.
На этой диаграмме показаны основные компоненты (каждый прямоугольник соответствует исходному файлу .ml с тем же именем):
Ethernet-кадры поступают от клиентских qube (таких как work или personal) или от sys-net.
Интернет-пакеты (IP) отправляются в firewall, который обращается к таблице NAT и правилам из QubesDB, чтобы решить, что делать с пакетом.
Если пакет следует отправить дальше, он использует router для отправки его выбранному получателю.
client_net следит за базой данных XenStore, предоставляемой dom0,
чтобы узнавать, когда клиентов нужно добавить или удалить.
Процесс загрузки:
config.ml описывает используемые библиотеки и параметры статической конфигурации (размер таблицы NAT).
Инструмент mirage использует это для генерации main.ml.main.ml инициализирует драйверы, выбранные в config.ml,
и вызывает функцию start в unikernel.ml.unikernel.ml подключает агенты Qubes, настраивает сетевые компоненты,
а затем ожидает запрос на завершение работы.Для разработки используйте скрипты test-mirage для развёртывания уникернела (qubes-firewall.xen) из вашей разработочной AppVM.
В первый раз это потребует немного больше настройки, но в дальнейшем будет гораздо быстрее. Например:
[user@dev ~]$ test-mirage dist/qubes-firewall.xen mirage-firewall
Waiting for 'Ready'... OK
Uploading 'dist/qubes-firewall.xen' (7454880 bytes) to "mirage-test"
Waiting for 'Booting'... OK
Connecting to mirage-test console...
Solo5: Xen console: port 0x2, ring @0x00000000FEFFF000
| ___|
__| _ \ | _ \ __ \
\__ \ ( | | ( | ) |
____/\___/ _|\___/____/
Solo5: Bindings version v0.7.3
Solo5: Memory map: 32 MB addressable:
Solo5: reserved @ (0x0 - 0xfffff)
Solo5: text @ (0x100000 - 0x319fff)
Solo5: rodata @ (0x31a000 - 0x384fff)
Solo5: data @ (0x385000 - 0x53ffff)
Solo5: heap >= 0x540000 < stack < 0x2000000
2022-08-13 14:55:38 -00:00: INF [qubes.rexec] waiting for client...
2022-08-13 14:55:38 -00:00: INF [qubes.db] connecting to server...
2022-08-13 14:55:38 -00:00: INF [qubes.db] connected
2022-08-13 14:55:38 -00:00: INF [qubes.db] got update: "/mapped-ip/10.137.0.20/visible-ip" = "10.137.0.20"
2022-08-13 14:55:38 -00:00: INF [qubes.db] got update: "/mapped-ip/10.137.0.20/visible-gateway" = "10.137.0.23"
2022-08-13 14:55:38 -00:00: INF [qubes.rexec] client connected, using protocol version 3
2022-08-13 14:55:38 -00:00: INF [unikernel] QubesDB and qrexec agents connected in 0.041 s
2022-08-13 14:55:38 -00:00: INF [dao] Got network configuration from QubesDB:
NetVM IP on uplink network: 10.137.0.4
Our IP on uplink network: 10.137.0.23
Our IP on client networks: 10.137.0.23
DNS resolver: 10.139.1.1
DNS secondary resolver: 10.139.1.2
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] connect 0
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] create: id=0 domid=1
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] sg:true gso_tcpv4:true rx_copy:true rx_flip:false smart_poll:false
2022-08-13 14:55:38 -00:00: INF [net-xen frontend] MAC: 00:16:3e:5e:6c:00
2022-08-13 14:55:38 -00:00: INF [ethernet] Connected Ethernet interface 00:16:3e:5e:6c:00
2022-08-13 14:55:38 -00:00: INF [ARP] Sending gratuitous ARP for 10.137.0.23 (00:16:3e:5e:6c:00)
2022-08-13 14:55:38 -00:00: INF [ARP] Sending gratuitous ARP for 10.137.0.23 (00:16:3e:5e:6c:00)
2022-08-13 14:55:38 -00:00: INF [udp] UDP layer connected on 10.137.0.23
2022-08-13 14:55:38 -00:00: INF [dao] Watching backend/vif
2022-08-13 14:55:38 -00:00: INF [memory_pressure] Writing meminfo: free 20MiB / 27MiB (72.68 %)
Уникернел, который тестирует межсетевой экран, доступен в подкаталоге test/.
Чтобы использовать его, запустите test.sh и следуйте инструкциям по настройке тестового окружения.
См. задачи с меткой "security" для уведомлений о безопасности, затрагивающих межсетевой экран.
См. LICENSE.md