Зачем enterprise блокирует USB
Начнём не с технологий, а с причины, по которой эта статья вообще нужна.
В физическом мире USB-порт — дыра в периметре. Воткнул флешку — и у тебя либо данные утекли, либо малварь приехала, либо оба сценария одновременно. Stuxnet, обнаруженный в 2010-м (но активный с ~2007), пробил air gap завода в Натанзе — первоначально через завербованного агента, а дальше распространялся через USB-накопители. FIN7 в 2021-22 годах рассылали по почте подарочные коробки (от имени Amazon и HHS) с «флешками» — на деле это были Arduino ATMEGA32U4, эмулирующие клавиатуру и набивающие PowerShell-команды быстрее любого оператора. Конечная цель — Cobalt Strike, затем ransomware (BlackMatter, REvil). BadUSB, продемонстрированный на Black Hat 2014, показал, что любое USB-устройство может прикинуться клавиатурой и вводить команды — и VID/PID фильтрация тут не спасёт, потому что идентификаторы прошиты в firmware и перешиваются за минуту.
VDI в теории решает часть проблем: данные живут на сервере, а не на эндпоинте. Но USB-редиректор эту изоляцию пробивает — если разрешить проброс mass storage, пользователь утащит файлы на флешку ровно так же, как с физического ПК. А если не разрешить — придут люди со смарт-картами и принтерами, и скажут «нам нужно работать».
Вот тут начинается инженерный компромисс, который не решается одним галочкой в политике.
USB-редиректор SPICE: как это устроено
usbredir — протокол, а не канал
Важно не путать: в SPICE есть канал SPICE_CHANNEL_USBREDIR (тип 9 в протоколе), но внутри него бежит отдельный, независимый протокол — usbredir, разработанный Red Hat и живущий в своём репозитории на gitlab.freedesktop.org/spice/usbredir. Текущая версия пакета — 0.15.0 (январь 2026), протокол — v0.7. Лицензия LGPLv2.1.
usbredir спроектирован так, чтобы не зависеть от SPICE — его можно использовать с VNC, по TCP-сокету, да хоть через SSH-туннель. SPICE просто предоставляет транспорт.
Что происходит, когда вы пробрасываете USB
[Физическое USB-устройство на клиенте] | libusb (userspace доступ к USB) | usbredirhost (управляет устройством, отдаёт трансферы) | usbredirparser (сериализация в wire-формат) | spice-gtk → SpiceUsbredirChannel | SPICE канал тип 9 (TCP, опционально TLS) | данные обёрнуты в SPICE_MSG_SPICEVMC_DATA | QEMU: chardev spicevmc + usb-redir device | Виртуальный USB-контроллер (EHCI/XHCI) | Гостевая ОС видит обычное USB-устройство
На клиенте всем рулит SpiceUsbDeviceManager (файл usb-device-manager.c в spice-gtk). Он следит за подключениями через libusb hotplug callbacks, фильтрует устройства и привязывает каждое к свободному SpiceUsbredirChannel. Один канал — одно устройство. Хотите три USB одновременно — конфигурируйте три пары chardev + usb-redir в QEMU.
На QEMU-стороне каждое устройство — это связка:
-chardev spicevmc,name=usbredir,id=usbredirchardev1 -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1
Wire-формат
Протокол передаёт не сырые USB-сигналы, а структурированные USB-трансферы: control, bulk, isochronous, interrupt. Всё little-endian, packed без паддинга. Каждый пакет начинается с заголовка:
// legacy-формат (без cap_64bits_ids): struct usb_redir_header { uint32_t type; // тип пакета uint32_t length; // длина данных после заголовка uint32_t id; // ID запроса }; // современный формат (cap_64bits_ids, бит 5): struct usb_redir_header_64 { uint64_t id; // ID запроса — теперь первое поле uint32_t type; uint32_t length; };
Порядок полей в 64-битном варианте другой — id переехал в начало. Совместимость обеспечивается через capabilities: если обе стороны заявили бит 5, используется новый формат. Определения обоих вариантов живут в usbredirproto.h и usbredirproto-compat.h.
Рукопожатие: обе стороны сразу шлют usb_redir_hello (тип 0) с версией и битовой маской capabilities. Потом хост отправляет информацию об эндпоинтах, интерфейсах и подключает устройство. Фича работает, только если обе стороны её заявили.
Детали capabilities (из usbredirproto.h):
Бит | Что даёт |
|---|---|
0 | USB 3.0 bulk streams (нужен libusb >= 1.0.19) |
2 | Фильтрация устройств |
5 | 64-битные ID пакетов |
6 | 32-битная длина bulk-трансферов |
7 | Буферизованный bulk input |
Все capabilities умещаются в один uint32_t. Протокол обратно совместим начиная с версии 0.3 — всё новое гейтится через capabilities, а не через номер версии.
Сжатие
spice-gtk умеет сжимать USB-данные LZ4. Условия: не Unix-сокет, данные больше 1000 байт, сервер заявил SPICE_SPICEVMC_CAP_DATA_COMPRESS_LZ4, и устройство не изохронное. Для isochronous-трафика сжатие явно отключено — задержка важнее размера.
USB 1/2/3
Версия | Контроллер в QEMU | Заметки |
|---|---|---|
USB 1.x | UHCI (companion к EHCI) | Нужен EHCI + UHCI комбо |
USB 2.0 | EHCI + companion UHCI | Самая протестированная конфигурация |
USB 3.0 | XHCI ( | Менее протестировано, но XHCI проще и жрёт меньше CPU |
XHCI поддерживает все версии USB (1.1/2.0/3.0), поэтому если не нужна совместимость со старыми гостевыми ОС — проще ставить только его.

Фильтрация: первая линия обороны
Формат фильтра
SPICE использует строковые правила: <class>,<vendor>,<product>,<version>,<allow>, склеенные через |. Значение -1 — wildcard. 1 = разрешить, 0 = запретить. Первое сработавшее правило побеждает. Если ни одно не сработало — устройство заблокировано.
Дефолтный фильтр автоподключения в spice-gtk:
0x03,-1,-1,-1,0|-1,-1,-1,-1,1
Расшифровка: запретить auto-connect для HID-устройств (класс 0x03 — клавиатуры, мыши), разрешить всё остальное. HID блокируется, чтобы вы случайно не перенаправили свою клавиатуру в VM и не потеряли управление клиентом.
Нюанс с разделителями: в spice-gtk внутри правила используется запятая, в QEMU — двоеточие. В libvirt — XML-атрибуты. Три разных синтаксиса для одной и той же логики, потому что каждый компонент парсит по-своему.
Примеры
# Блокировать mass storage, разрешить остальное 0x08,-1,-1,-1,0|-1,-1,-1,-1,1 # Разрешить только конкретное устройство (VID:PID), всё остальное — нет -1,0x1234,0x5678,-1,1|-1,-1,-1,-1,0 # Блокировать HID + mass storage, разрешить rest 0x03,-1,-1,-1,0|0x08,-1,-1,-1,0|-1,-1,-1,-1,1
Три уровня фильтрации
Клиент: auto-connect-filter — при подключении нового устройства, нужно ли его автоматически пробрасывать
Клиент: redirect-on-connect — при подключении к SPICE-сессии, какие уже воткнутые устройства пробросить
QEMU / libvirt: redirfilter — серверная сторона, последний рубеж
Почему фильтрация — необходимость, но не решение
VID/PID и device class — это то, что устройство говорит о себе. Firmware может заявить любой класс. BadUSB-флешка представляется как HID-клавиатура и начинает набирать powershell -enc ... быстрее, чем вы моргнёте. Фильтрация по классу помогает от случайного проброса (не перехватить мышь, не дать пользователю воткнуть random-флешку), но не от целенаправленной атаки.
Если ваша threat model включает state-level adversary или инсайдера с паяльником — USB-редиректор нужно отключать полностью. Если включает «сотрудник случайно принёс вирусную флешку» — класс-ф��льтрация плюс DLP на уровне гостевой ОС покрывают основное.
Безопасность: что реально опасно, а что — театр
Что VDI даёт
Сетевой USB-редиректор (usbredir через TCP) — это не прямое подключение к шине. Устройство общается с USB-стеком клиентской машины, а в VM приезжают только сериализованные USB-трансферы. Из этого следует:
DMA-атаки невозможны. Thunderbolt/PCIe DMA — это когда устройство напрямую пишет в память хоста. Через сетевой редиректор устройство видит только клиентский USB-стек, а до памяти хоста/VM добирается только через QEMU-эмуляцию. Никакого прямого доступа.
Firmware-атаки на физический USB-контроллер — только на стороне клиента. VM получает уже распарсенные данные.
VM-изоляция работает. Если малварь попала через USB в гостевую ОС — она заперта в VM. Если VM создаётся из snapshot и сбрасывается после сессии — ущерб ограничен.
Что VDI НЕ даёт
QEMU USB-эмуляция — это attack surface. USB-эмуляция в QEMU исторически богата на CVE. Исследование 2025 года по Cross-Domain Attacks (arxiv: 2512.04260) показало, что ~23.9% CVE в QEMU за последние пять лет приводят к pointer corruption — не обязательно эксплуатабельны, но потенциально опасны, включая USB-подсистему. Crafted USB-пакеты от малициозного клиента теоретически могут атаковать QEMU через usb-redir device.
usbredir тоже не без греха. CVE-2021-3700: use-after-free в usbredirparser_serialize() при медленной отправке. CVSS 6.4 (Medium), вектор локальный, сложность эксплуатации высокая, нужны повышенные привилегии. Автор описал как denial-of-service или потенциальное выполнение кода, но надёжная эксплуатация нереалистична. Исправлено в 0.11.0.
Data exfiltration через mass storage работает ровно так же, как на физическом ПК, если класс 0x08 не заблокирован.
Без TLS USB-трафик виден на сети в открытом виде. Всё, что передаётся через USB — данные с токенов, содержимое флешек, APDU смарт-карт — читается снифером.
Сравнение attack surface
Вектор | Физический USB | USB через VDI (usbredir) |
|---|---|---|
Data exfiltration | Прямой | Работает, если mass storage разрешён |
BadUSB / HID spoofing | Высокий риск | Блокируется дефолтным HID-фильтром |
DMA | Высокий (Thunderbolt) | Невозможен |
Firmware-атаки на контроллер | Прямой | Только клиентская сторона |
Эксплойт драйвера в ОС | Риск для хоста | Изолирован в VM |
Побег из VM через USB-эмуляцию | N/A | Редко, но возможно |

Смарт-карты: исключение, которое подтверждает правило
Смарт-карты — единственная категория USB, которую enterprise хочет пробрасывать. CAC/PIV для госструктур США, корпоративные PKI-карты для аутентификации — без них VDI не развернёшь. При этом карта не создаёт риска data exfiltration: приватный ключ не покидает чип.
Два способа проброса
В SPICE есть два пути. И выбор между ними — не очевидный.
Способ 1: Dedicated smartcard channel (канал 8)
SPICE имеет выделенный канал SPICE_CHANNEL_SMARTCARD = 8 с собственным внутренним протоколом VSC (Virtual Smart Card). Работает через libcacard — библиотеку, которую Red Hat изначально писали для CAC-карт (Common Access Card). Архитектура:
Физическая карта → PC/SC (pcscd) → NSS/PKCS#11 → libcacard → SPICE smartcard channel (канал 8, VSC-протокол) → QEMU: ccid-card-passthru → usb-ccid → Гость видит USB CCID-ридер с виртуальной картой
Ключевое: libcacard не пробрасывает сырой USB. Она перехватывает криптографическую идентичность карты через NSS/PKCS#11 на клиенте и эмулирует виртуальную CAC-карту. Через SPICE-канал передаются APDU-команды (ISO 7816), а не USB bulk-трансферы.
Но тут важный нюанс. libcacard может работать в двух режимах: ccid-card-emulated и ccid-card-passthru. В emulated-режиме криптооперации (подпись, расшифровка) выполняются на клиенте через NSS, и PIN обрабатывается локально — в сеть не уходит. А вот в passthru-режиме (который конфигурируется ниже в этой статье) APDU-команды пробрасываются целиком, включая VERIFY PIN (ISO 7816 INS 0x20). То есть PIN всё-таки передаётся по SPICE-каналу. Без TLS — в открытом виде.
Emulated-режим безопаснее, но требует NSS и PKCS#11-модуль карты на клиенте, и работает только с CAC-совместимыми картами. Passthru проще в настройке и поддерживает больше типов карт, но жертвует изоляцией PIN.
Способ 2: USB-проброс ридера (канал 9, usbredir)
Пробрасываете физический USB-ридер целиком через usbredir. Гость получает exclusive доступ к устройству. Простая настройка. Но: весь USB-трафик, включая PIN, идёт по сети (в открытом виде без TLS). И карта недоступна на клиенте, пока проброшена в VM.
Сравнение
Smartcard channel (8) | USB redirection (9) | |
|---|---|---|
Карта доступна на клиенте | Да | Нет (exclusive) |
PIN по сети | Emulated — нет; Passthru — да (в APDU) | Да (в USB-трафике) |
Поддержка типов карт | Только CAC (libcacard) | Любые |
Настройка | Сложнее (NSS, PKCS#11) | Проще |
Attack surface | Меньше (APDU only) | Больше (полный USB-стек) |
Composite-устройства (Yubikey) | N/A | Проблемы ( |
Ограничения libcacard
Тут нужна честность. libcacard заточена под CAC и реализует только аплеты, нужные CoolKey PKCS#11 драйверу. PIV (NIST SP 800-73) аплетов в ней нет — PIV-карты работают опосредованно через PKCS#11 на клиенте, если OpenSC или аналог установлен. Начиная с libcacard v2.7.0 добавили Microsoft PnP applet и совместимость с ActivClient, что улучшило ситуацию на Windows-гостях.
Но для реальных военных/государственных деплоев с CAC-NG / PIV-II картами open-source стек часто недостаточен — используют коммерческий middleware (ActivClient, 90Meter). И нередко вообще уходят на RDP smart card redirection, потому что он надёжнее.
Развитие libcacard вялое: основной репозиторий на gitlab.freedesktop.org/spice/libcacard, последняя версия 2.8.x, активность низкая.
FIDO2/WebAuthn через VDI
Отдельная боль. USB-ключи типа YubiKey — composite-устройства (HID + CCID + U2F/FIDO2), и proбросить их через usbredir часто не получается. Citrix решила это через HDX FIDO2 virtual channel — перехватывает WebAuthn API на уровне браузера и редиректит на клиент, без USB-проброса вообще. VMware делает аналогичное.
В SPICE этого нет. Если нужен FIDO2 в SPICE-based VDI — либо мучаетесь с usbredir (и готовьтесь к LIBUSB_ERROR_NOT_SUPPORTED на Yubikey 4/5), либо выносите аутентификацию за пределы VDI-сессии.
Конфигурация в QEMU
Для smartcard channel:
qemu-system-x86_64 ... \ -usb \ -device usb-ccid \ -chardev spicevmc,name=smartcard,id=ccid \ -device ccid-card-passthru,chardev=ccid
В libvirt:
<smartcard mode="passthrough" type="spicevmc"/>
Гость (Windows): увидит USB CCID-ридер в Device Manager, загрузит встроенный Microsoft USBCCID-драйвер автоматически. Для самой карты нужен middleware — CoolKey, OpenSC, или ActivClient.
Гость (Linux): нужен pcscd + OpenSC (или CoolKey, если RHEL 7 и ранее; с RHEL 8 дефолт — OpenSC).

Принтеры: дыра, о которой молчат
В SPICE нет печатного канала
Вот полный список каналов протокола SPICE:
Тип | Канал | Назначение |
|---|---|---|
1 | MAIN | Управление сессией, vdagent |
2 | DISPLAY | Картинка |
3 | INPUTS | Клавиатура, мышь |
4 | CURSOR | Курсор |
5 | PLAYBACK | Звук → клиент |
6 | RECORD | Микрофон → гость |
7 | TUNNEL | Устаревший, удалён |
8 | SMARTCARD | Смарт-карты |
9 | USBREDIR | USB-редиректор |
10 | PORT | Произвольный байт-стрим |
11 | WEBDAV | Общие папки |
Принтера нет. Был proposal в 2012 году (в spice-devel от Charles Tsai), Alon Levy из Red Hat подробно расписал архитектуру — chardev subtype printer, новый канал по аналогии с usbredir. Не реализовано. Тот устаревший TUNNEL (тип 7) изначально планировался, в том числе, для доступа к клиентским принтерам — но канал deprecated и удалён, замены не появилось.
Как люди всё-таки печатают
На практике есть четыре подхода, ни один из которых не элегантен:
1. Сетевая печать (IP/IPP): Гость печатает напрямую на сетевой принтер. Работает, если VM-сеть видит принтерную подсеть. Нужны драйверы в госте. Самый надёжный вариант для enterprise, но не помогает с локальными принтерами на тонком клиенте.
2. USB-проброс принтера: Через usbredir. Один пользователь — одна VM — один принтер (exclusive access). Нужны драйверы в госте. На Proxmox-форумах есть тред с 2013 года, где люди до сих пор обсуждают BSOD от некоторых принтеров при пробросе. Live migration с пробросом USB невозможна.
3. WebDAV + print-to-file: Печать в PDF через виртуальный принтер (CUPS-PDF на Linux, Microsoft Print to PDF на Windows), файл падает в общую WebDAV-папку SPICE (канал 11), клиент забирает. Работает, но пользовательский опыт — «сохрани PDF, найди его, открой, распечатай». Не для call-центра.
4. CUPS forwarding: Для Linux→Linux сценариев: CUPS на хосте расшаривает принтеры по IPP, гость добавляет их. Driverless IPP Everywhere минимизирует потребность в драйверах. Через NAT нужен port forwarding.
А у Citrix и VMware?
Citrix и VMware решили проблему принтеров много лет назад:
Citrix Universal Print Driver (UPD): Один универсальный драйвер на сервере, который перехватывает print job в формате EMF/XPS. При логине в сессию принтеры клиента автоматически маппятся. Сервер захватывает print job через UPD, сжимает и отправляет по ICA virtual channel на клиент. Финальный рендеринг под конкретное устройство (device-specific) происходит уже на клиенте нативным драйвером. Гостю не нужны драйверы конкретных принтеров — в этом и суть.
VMware / ThinPrint: Аналогичная схема: Output Gateway на виртуальном десктопе (единственный «драйвер»), AutoConnect при логине, сжатие до 98%, нативный рендеринг на эндпоинте.
Сравнение:
SPICE | Citrix UPD | VMware/ThinPrint | |
|---|---|---|---|
Выделенный print-канал | Нет | Да (ICA VC) | Да |
Универсальный драйвер | Нет | Да | Да |
Auto-mapping принтеров | Нет | Да | Да |
Сжатие print-трафика | Нет | Да | Да (до 98%) |
Драйвер-free гость | Нет | Да | Да |
Это одна из самых заметных gap между SPICE и коммерческими решениями. Если в ТЗ на VDI есть «печать на локальные принтеры» — SPICE потребует значительно больше костылей.

Что реально используют на Proxmox
Судя по форумам (а форумы Proxmox — неплохой срез реальных деплоев):
RDP вместо SPICE для сессий, требующих печати. RDP printer redirection работает из коробки.
Сетевые принтеры по IP — для Linux-гостей.
Выделенная print server VM (Ubuntu + CUPS + Samba) — чтобы не ставить CUPS на хост Proxmox.
USB passthrough на уровне хоста (
usb0: host=VENDOR:PRODUCTв conf-файле VM) — для физических USB-принтеров, но только один пользователь, нужен полный stop/start VM.
Compliance: что требуют стандарты
Не абстрактно, а конкретно.
PCI-DSS v4.0 (обязателен с 31 марта 2025):
3.4.2: технические контроли, предотвращающие копирование PAN на removable media при использовании remote-access technologies — требование распространяется именно на сценарий удалённого доступа, что включает VDI
5.3.3: сканирование removable media антималварью перед использованием (обязательно, не рекомендация)
NIST SP 800-53 Rev. 5:
MP-7 (Media Use): организация должна ограничить или запретить использование определённых типов media. Portable storage без идентифицируемого владельца — запретить
MP-2, MP-5, MP-6: контроль доступа, транспорта и санитизации media
На практике типичная enterprise USB-политика:
Весь removable storage заблокирован по дефолту (GPO / Intune)
Исключения — только по конкретному hardware ID, с подписью руководителя
Аудит всех USB-подключений
Smart cards — разрешены (отдельная категория, класс 0x0B)
Для SPICE-based VDI это значит: usbredir-каналы лучше не конфигурировать вообще (нет канала — нет проброса — нет attack surface), а если конфигурировать — с серверным redirfilter, который блокирует mass storage и HID, оставляя только то, что реально нужно.
Практическая конфигурация
USB-проброс: базовая настройка
qemu-system-x86_64 ... \ -device nec-usb-xhci,id=usb \ -chardev spicevmc,name=usbredir,id=usbredirchardev1 \ -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1 \ -chardev spicevmc,name=usbredir,id=usbredirchardev2 \ -device usb-redir,chardev=usbredirchardev2,id=usbredirdev2
Два слота = два устройства одновременно. XHCI проще, чем EHCI+UHCI комбо, и поддерживает USB 1.1/2.0/3.0.
В libvirt:
<controller type='usb' model='nec-xhci'/> <redirdev bus='usb' type='spicevmc'/> <redirdev bus='usb' type='spicevmc'/>
Серверный фильтр (блокировать mass storage):
<redirfilter> <usbdev class='0x08' vendor='-1' product='-1' version='-1' allow='no'/> <usbdev class='-1' vendor='-1' product='-1' version='-1' allow='yes'/> </redirfilter>
Smart card: dedicated channel
qemu-system-x86_64 ... \ -usb \ -device usb-ccid \ -chardev spicevmc,name=smartcard,id=ccid \ -device ccid-card-passthru,chardev=ccid
Libvirt:
<smartcard mode="passthrough" type="spicevmc"/>
QEMU должен быть собран с --enable-smartcard. На клиенте нужен NSS + PKCS#11 модуль (OpenSC или CoolKey).
WebDAV (для print-to-file и файлообмена)
Libvirt:
<channel type='spiceport'> <source channel='org.spice-space.webdav.0'/> <target type='virtio' name='org.spice-space.webdav.0'/> </channel>
В госте: установить spice-webdavd. Windows-гость увидит \\localhost@9843\DavWWWRoot. Linux — через gvfs/Nautilus.
Windows-клиент: нужен UsbDk
Для USB-редиректа на Windows-клиенте нужен UsbDk — фильтр-драйвер, дающий userspace-доступ к USB-устройствам. Без него проброс не заработает.
Производительность USB-редиректора: чего ожидать
Bulk-трансферы (флешки, принтеры)
Работают приемлемо. С cap_32bits_bulk_length поддерживаются трансферы до ~4 ГБ. USB 3.0 bulk streams добавляют пропускную способность. На скорость влияет сеть — не ожидайте USB 3.0 speeds через WAN.
Isochronous (веб-камеры, USB-аудио)
Самое проблемное. usbredir дропает isochronous-пакеты при переполнении write queue. На практике:
Веб-камеры могут отваливаться через несколько минут
USB-аудио glitches под нагрузкой
Сжатие для isochronous отключено (latency-sensitive)
Синхронизации между аудио и видео нет
Если нужна камера в VDI — лучше выделенный протокол (Citrix HDX RealTime, VMware RTAV). SPICE usbredir для камер — крайний случай.
Interrupt-трансферы (клавиатуры, мыши, HID)
Работают, но вы не должны их пробрасывать (HID блокируется по умолчанию). Для клавиатуры и мыши SPICE использует собственный INPUTS-канал (тип 3), который оптимизирован под это.
Вот итог — написал так, чтобы он не просто повторял "коротко" из статьи, а давал читателю ощущение завершённости и практического вывода:
Итог: компромисс, который придётся принять
USB-редиректор в SPICE — это не фича безопасности и не дыра в периметре. Это инструмент, который делает ровно то, что ему говорят. Если говорить «пробросить всё» — пробросит всё, включая потенциальную малварь с флешки. Если говорить «только смарт-карты и ничего больше» — будет именно так. Проблема в том, что пространство между «запретить всё» и «разрешить всё» — это не один ползунок, а несколько десятков мелких решений, каждое из которых имеет последствия.
Для большинства enterprise-деплоев разумный минимум выглядит так: usbredir-каналы без крайней необходимости не открывать, mass storage блокировать серверным redirfilter как последним рубежом, смарт-карты пробрасывать через dedicated channel (8), а не через usbredir, TLS считать обязательным, а не опциональным. Это не паранойя — это то, что PCI-DSS и NIST уже давно считают само собой разумеющимся.
Честный ответ на вопрос «насколько SPICE готов к enterprise USB?»: зависит от того, что вы называете enterprise. Если это сотрудники за рабочими станциями с сетевыми принтерами и CAC-картами — SPICE справится, пусть и с усилиями. Если это call-центр с локальными USB-принтерами, FIDO2-ключами и требованием auto-mapping — вы скорее всего в какой-то момент откроете документацию Citrix.
SPICE — хороший открытый протокол с понятной архитектурой и честными trade-off. Его ограничения в области USB — не баги, это следствие того, что коммерческий функционал типа Universal Print Driver или HDX FIDO2 требует лет инженерных усилий и нормального финансирования. Проекту это не досталось. Зато досталась прозрачность: исходники открыты, протокол задокументирован, поведение предсказуемо.
Именно поэтому с ним стоит работать осознанно — понимая, где он тянет, а где придётся либо дорабатывать, либо выбирать другой инструмент.
