Заметки дилетанта широкого профиля

RSS

Как я решил ознакомится с Proxmox VE, но обнаружил что он не нужен

А эта заметка будет про Proxmox VE! Решил я, значится, обратить на него своё внимание. Просто нахожусь в процессе трудоустройства, а у нас тут, в вакансиях на рынке труда, что-то часто Proxmox стали через дробь указывать в требованиях, аккурат в соседстве с софтом от VMware. Что удивительно. Было бы логичней там, в соседстве с продуктами VMware, видеть какой-нибудь OpenStack или oVirt, но нет, там Proxmox всё чаще встречается… А я вот развернул этот самый Proxmox VE и остался убеждён, что он, во-первых, не то, чтобы и нужен сам по себе, но и, во-вторых, не готов совсем для продакшна. И дело не в том, что фитч каких-то не завезли, нет. Фитч там с избытком! Но там с базовыми вещами есть проблемы, неучтённые разработчиками и старательно игнорируемые пользователями.

Пару слов об виртуализации в ОС на базе ядра Linux и своём опыте

Любой, кто в профессии давно, а не вчера забрёл на огонёк, в курсе, что главным строительным кирпичиком linux-based виртуализации является QEMU. KVM лишь решил в некоторой степени вопрос с низкой производительностью QEMU, сделав возможным применение инструкций аппаратной виртуализации вместо полной эмуляции процессора и памяти. В «некоторой степени», потому что, например, паравиртуализация ввода-вывода, являющаяся тоже важной частью мер по увеличению быстродействия, велась в рамках самого QEMU. Впрочем, и это важно, QEMU был готов исполнять виртуальные машины, в том числе как средство виртуализации на сервере, несколько до момента появления KVM в основной ветке ядра. Потому что всё нужное для этого уже было в QEMU: и возможность скормить ему образы виртуальных машин самым разным способом (хоть из файла на локальной файловой системе или NFS, хоть блочное устройство по AoE/NBD/iSCSI/как-угодно-ещё, притом вариантов было больше, чем у любого коммерческого решения), и подцепить сеть практически как угодно, и даже средства по уходу в фон и актуализации собственного PID-файла присутствовали. Вот просто берёшь тот QEMU и делаешь из него нормального такого демона штатными средствами самого же QEMU. Это же просто великолепное-великолепие, когда можно виртуальные машины органично встроить в логику работы хостовой ОС, превратив каждую из них в штатный сервис, просто написав для каждой свой файл в rd.d!

И не смотри, что с такими вводными, развернуть свой сервер с виртуальными машинами было не сложней, чем несколько инстансов Апача на одной машине. Всё равно была толпа «Тру ЫнтерпрайзЪ Одменов», которые могли даже бахваляться работой под Gentoo (то есть отсутствием страха или недопонимания работы с cli), но маниакально продолжавших держаться за какой-нибудь VMware GSX Server. Потому что там был web-интерфейс.

Понятное дело, был сценарий, когда требовалось наличие какого-то интерфейса, позволявшего централизованно управлять СЕРВЕРАМИ. Ну когда их было несколько больше одного. И когда каждый из них был уже не отдельной сущностью, но безликой платформой. И тогда абстракция происходила от СХД и виртуальных машин. А Red Hat, желая влезть на рынок виртуализации, поставили себе целью централизованно управлять более чем одним типом виртуальных машин. Так что они пошли разрабатывать слой абстракций, который позволил бы управлять многими серверами за раз, притом серверами, на которых применялись бы, в том числе, разные типы виртуализации. Так получился libvirt. На старте у libivrt’а было два способа администрирования: консольный клиент с весьма упоротым синтаксисом и глючащий GUI на python. Кстати, чуть позже Red Hat выкупили разработчиков KVM. Так что Red Hat обзавелись уже не только мотком изоленты (т. е. libvirt’ом), но ещё и собственным строительным материалом (то есть связкой QEMU+kvm).

И вот только появление libvirt’а хоть как-то помогло обратить внимание «Тру ЫнтерпрайзЪ Одменов» на QEMU/KVM. До этого они скорее на Xen обращали внимание, а тот, в те времена, был весьма проблемным явлением. Но мало ли, что проблемным, - ведь у него был консольный инструмент управления! У QEMU он тоже был, т.н. QEMU-monitor. Но это надо было что-то узнать о предмете, как-то его под себя приспособить. Это всё, как понимаете, не про «Тру ЫнтерпрайзЪ Одменов». Те, если нет у инструмента «супер-специальной-утилиты-управления», на такое даже не посмотрят. Ынтерпрайз он такой, да… Даже когда дело касается управления ЕДИНСТВЕННЫМ сервером виртуализации на предприятии. И вот libvirt помог обратить вниманием ТАКИХ «специалистов» на QEMU/KVM. Это жеж теперь появился GUI-клиент, чтобы сервером рулить! А самые крутые из этой братии даже смогли заучить пару-тройку заклинаний для virsh.

И за бортом по-прежнему оставались граждане, чьи навыки не простирались дальше квеста по установке Windows на ПК. Им бы вот какое-то «коробочное» решение, чтобы «Тык-Тык-И-в-Продакшн». И вот эту нишу и занял собой Proxmox VE. Он представлял собой самостоятельный велосипед для запуска виртуальных машин и конфигурирования сервера, никак не завязанный на libvirt. Но не за независимость от воли Red Hat его оценили. А за то, что он позволял в пару кликов установить нечто, напоминавшее идеологически VMware GSX. То есть даже вчерашние виндо-админы получили решение, которое дало им не только производительную и стабильную виртуализацию, но ещё возможность не вникая в вопрос делать бэкапы по расписанию, «цеплять» хранилища и всё такое. А ещё оно понравилось, что не удивительно, «Тру ЫнтерпрайзЪ Одменам». Кто бы сомневался, собственно?

Пару слов за безопасность виртуальных машин

Во-первых, в виртуальной машине, использующей аппаратные средства виртуализации, производится виртуализация процессора и его адресного пространства теми самыми аппаратными средствами оборудования хост-системы. Есть фрагменты кода гипервизора, которые вызываются при подготовки аппаратных средств к виртуализации, чтобы подготовить виртуальное окружение. Есть фрагменты кода, которые вызываются для обработки некоторых событий виртуального окружения. И вот в этих фрагментах если есть ошибки, или есть ошибки в реализации инструкций виртуализации в самом оборудовании хост-системы, то возможен выход из виртуальной машины и исполнения кода в среде хост-машины. Более того, те же intel весьма специфично реализовали инструкции виртуализации, отчего даже среда исполнения ОС хост-машины, фактически, является высокопривилегированной виртуальной машиной. А выход за пределы изоляции из гостя позволяет атакующему иметь большие привилегии и доступ, чем есть даже у ОС хост-системы. Успешная эксплуатация такой уязвимости — это буквально худший сценарий из всех возможных.

Во-вторых, в виртуальной машине виртуализируется и какое-то оборудование применяемое, например, для вводы-вывода. И вот его код исполняется в пространстве пользователя хост-ОС. То есть если этот код сдержит ошибки, позволяющие выполнить произвольный код из гостя в хост-системе, то он будет исполняться с правами того пользователя, от которого запущена виртуальная машина. Это как бы тоже огромная проблема, если такую уязвимость проэксплуатируют, но её масштабы можно сильно уменьшить рядом мер. И самая явная из них — не исполнять виртуальные машины от root’а. А в версиях QEMU после 2012 года даже добавился механизм изоляции системных вызовов через seccomp ядра ОС. Ну чтобы, если даже уязвимость проэксплуатируют, у атакующего были крайне ограничены возможности по скрытию взлома, эскалации своих привилегий или эксплуатации уязвимостей непосредственно хост-окружения. И единственно правильной стратегией является совмещение обоих подходов, когда QEMU изначально исполняется от пользователя с минимально возможными правами, плюс sandbox’инг вызовов, которые не требуются непосредственно для работы QEMU. И именно так оно, лет пять уже как, только и запускается через libvirt. А в моей системе управления виртуализацией и вовсе машины по отдельным пользователям были раскиданы (а чтобы и нет, когда пара-тройка серверов, а не кластер в десятки-сотни машин?).

И это всё, попрошу заметить, не какая-то там беспочвенная паранойя. Смотрите на CVE-2021-3748, например, с потенциальной возможностью исполнения кода. Или более свежий CVE-2024-6519. Об этом даже есть бюллетень от Cannonical USN-8161-1.

А что Proxmox?

Таки смотрите сами:

root@proxmox-sucks:~# ps axu | grep qemu
root        1173 29.1  0.4 988564 40464 ?        Sl   05:56   0:07 /usr/bin/kvm
-id 100
-name vm100,debug-threads=on
-no-shutdown
-chardev socket,id=qmp,path=/var/run/qemu-server/100.qmp,server=on,wait=off
-mon chardev=qmp,mode=control
-chardev socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000
-mon chardev=qmp-event,mode=control
-pidfile /var/run/qemu-server/100.pid
-daemonize
-smbios type=1,uuid=40866068-40f8-4910-bdb0-b46c3acb5e71
-smp 1,sockets=1,cores=1,maxcpus=1
-nodefaults
-boot menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg
-vnc unix:/var/run/qemu-server/100.vnc,password=on
-cpu qemu64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt
-m 512
-object {"id":"throttle-drive-ide0","limits":{},"qom-type":"throttle-group"}
-global PIIX4_PM.disable_s3=1
-global PIIX4_PM.disable_s4=1
-device pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e
-device pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f
-device vmgenid,guid=c53cb531-b250-474a-8b7e-3efd669ef355
-device piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2
-device usb-tablet,id=tablet,bus=uhci.0,port=1
-device cirrus-vga,id=vga,bus=pci.0,addr=0x2
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on
-iscsi initiator-name=iqn.1993-08.org.debian:01:9d2062db5753
-blockdev {"detect-zeroes":"on","discard":"ignore","driver":"throttle",
"file":{"cache":{"direct":true,"no-flush":false},"detect-zeroes":"on",
"discard":"ignore","driver":"raw","file":{"aio":"io_uring",
"cache":{"direct":true,"no-flush":false},"detect-zeroes":"on",
"discard":"ignore","driver":"host_device","filename":"/dev/pve/vm-100-disk-0",
"node-name":"e69016a06abcb44375c8e8c5346a52c","read-only":false},
"node-name":"f69016a06abcb44375c8e8c5346a52c","read-only":false},
"node-name":"drive-ide0","read-only":false,"throttle-group":"throttle-drive-ide0"}
-device ide-hd,bus=ide.0,unit=0,drive=drive-ide0,id=ide0,bootindex=100,write-cache=on
-device ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=101
-netdev type=tap,id=net0,ifname=tap100i0,script=/usr/libexec/qemu-server/pve-bridge,
downscript=/usr/libexec/qemu-server/pve-bridgedown
-device rtl8139,mac=BC:24:11:64:2D:98,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=102
-rtc driftfix=slew,base=localtime
-machine type=pc-i440fx-10.1+pve0
Достаточно просто посмотреть на процесс виртуальной машины, чтобы всё понять

Оно, во-первых, исполняется от имени пользователя root. Во-вторых, оно не использует изоляцию системных вызовов (отсутствует аргумент '-sandbox'). И тут два варианта: либо разработчики вообще не задумывались об том, что же необходимо сделать для обеспечения хоть какой-то безопасности хост-окружения, либо им настолько не хотелось отказываться от ухода в фон средствами самого QEMU (тогда перестал бы работать аргумент запуска '-daemonize', а они его используют), что они просто решили проигнорировать этот аспект. Если проблема в первом заключается - это многое говорит о самом проекте. Если во втором - то о программистах проекта, так как решается банальным fork() в родительском процессе, поэтапным сбросом привилегий, закрытием дескрипторов, с последующим exec() в дочернем процессе. Уже с '-sandbox' в аргументах.

Главная проблема Proxmox - пользователи Proxmox

Неужели никто из пользователей Proxmox'а не заметил вот этого? Не задумался над тем, насколько безопасно пользоваться Proxmox'ом? Неужели настолько низок уровень экспертизы у сообщества? Им вообще не интересно, как оно там живёт, что ли? Но, если вспомнить о том, что Proxmox, фактически, стал этакой бесплатной заменой VMware, то ничего удивительного. «Тру ЫнтерпрайзЪ Одменам» вообще никогда ничего не было интересно. Особенно тем, чей потолок ещё вчера был - установщик Windows. Ну а теперь они настоящие админы, способные развернуть и сервер виртуализации, и почтовый сервер. Только на первом Proxmox, а на втором - Zimbra. А что там внутри никто из подобных персонажей толком не знает. Да и, если спросить об этом, тебе лишь на кучу незакрытых тикетов в Jira потыкают. Нет времени думать, понимаешь, надо "клац-клац-тикет-закрывать", потому что важно успеть до очередного созвона с менеджером.

И я не просто так упоминал выше Red Hat, а так же oVirt и OpenStack. Входной порог этих продуктов гораздо выше. Необходимо вообще как-то задуматься об архитектуре своего кластера ДО момента начала работ по развёртыванию. Но это нормально, что инструмент для серьёзных задач требует подготовки, в отличии от игрушки, где даже сброс привилегий для виртуальных машин не организовали.

Отдельно хотелось бы отметить, что Proxmox VE поставляется в ALT Linux как одна из сред промышленной виртуализации. А они, интересно, вот это всё учли? Или нет времени об этом думать, надо импортозамещением заниматься?

И главное не забывать, что знание Proxmox VE нынче цениться на рынке труда. Такое вот у нас IT, и другого у нас нет. И оно всегда таким было, достаточно лишь вспомнить Webmin и типов на форуме с "помогите только ОС поставить и Webmin, а дальше я сам".