Привет, Хабр! В прошлой статье мы рассмотрели историю и принцип работы технологии USB over IP, узнали, как ее применяют на базе готового аппаратного решения.
Для личного использования, однако, аппаратное решение скорее не подойдет: нужно приобретать дорогостоящее оборудование, что нецелесообразно. Поэтому под катом рассказываю, как организовать клиент-серверный комплекс USB over IP на современных ОС и автоматизировать этот процесс.
Итак, USBIP прекрасно работает не только на специализированном оборудовании, но и на современных операционных системах. Это позволяет недорого или вообще без денежных вложений решать небольшие кейсы.
В данной статье мы рассмотрим организацию клиент-серверного комплекса USB over IP. В качестве клиента выступит облачный сервер Selectel (ОС — Ubuntu 20.04), а сервером будет классический bare metal-сервер, с той же версией Ubuntu. Помимо облачного клиента на Linux, мы выполним проброс устройства на клиент Windows 10.
Настройка сервера
Для начала установим необходимые инструменты и модули для работы. Все необходимые модули входят в состав пакета linux-tools. Выполняем его установку (у меня версия 5.4.0-100-generic):
root@Descartes:~# apt-get install linux-tools-`uname -r`
Далее проверяем доступные для загрузки USBIP модули ядра:
root@Descartes:~# find /lib/modules/$(uname -r) -name '*.ko'| grep usbip
/lib/modules/5.4.0-100-generic/kernel/drivers/usb/usbip/usbip-core.ko
/lib/modules/5.4.0-100-generic/kernel/drivers/usb/usbip/usbip-host.ko
/lib/modules/5.4.0-100-generic/kernel/drivers/usb/usbip/vhci-hcd.ko
/lib/modules/5.4.0-100-generic/kernel/drivers/usb/usbip/usbip-vudc.ko
Для работы сервера нам потребуются:
- usbip-core — основа USBIP-сервера,
- usbip-host — управление USB-устройствами,
- vhci-hcd — модуль экспорта виртуальных USB-устройств.
Выполним запуск необходимых нам модулей:
root@Descartes:~# modprobe usbip-core
root@Descartes:~# modprobe usbip-host
root@Descartes:~# modprobe vhci-hcd
Чтобы не запускать данные модули вручную каждый раз, добавим их в конфигурационный файл modules.conf:
root@Descartes:~# vi /etc/modules-load.d/modules.conf
usbip-core
usbip-host
vhci-hcd
Чтобы USB-сервер работал в фоновом режиме, мы запустим его в качестве демона, а после проверим BusID подключенного накопителя. Этот ID понадобится нам позже для проброса ключей в клиентскую часть. Запускаем USB-сервер в качестве демона:
root@Descartes:~# usbipd -D
Проверяем список подключенных устройств:
root@Descartes:~# usbip list -l
- busid 1-1 (058f:6387)
unknown vendor : unknown product (058f:6387)
- busid 1-13.1 (0557:2419)
unknown vendor : unknown product (0557:2419)
где BusID 1-1 — это наш USB-накопитель, подключенный в сервер.
Так как теперь нам известен BusID флешки, которой мы хотим поделиться с внешним миром, выполним следующую команду:
root@Descartes:~# usbip bind -b 1-1
usbip: info: bind device on busid 1-1: complete
Теперь устройство готово быть подключенным к удаленным клиентским устройствам. Далее рассмотрим настройку клиентской части.
Настройка клиента на Linux
По аналогии с сервером нам потребуется пакет linux-tools под необходимую версию ядра. Выполняем установку:
root@Racio:~# apt-get install linux-tools-`uname -r`
Подключаем удаленное устройство:
root@Racio:~# usbip attach --remote=188.124.55.21 --busid=1-1
Находим подключенный девайс среди остальных блочных устройств. В клиентской системе девайс определился как sda4-устройство:
root@Racio:~# fdisk -l
Device Boot Start End Sectors Size Id Type
/dev/sda4 * 256 31129599 31129344 14.9G c W95 FAT32 (LBA)
Настройка клиента на Windows
Одним из вариантов подключения устройств для Windows является использование отдельного ПО — VirtualHere USB Client. Эта программа практически исключает какую-либо настройку руками.
Но мы пойдем по более интересному пути, где для Windows-клиента проброс будет осуществлен с помощью пакета usbip-client. Этот пакет содержит необходимые конфигурационные файлы для работы, в том числе каталог безопасности. Благодаря нему в будущем у нас не возникнет проблем с сертификатами. Пакет работает с Windows 7 и 10, а также с Windows Server 2008 и 2021.
Распакованный usbip-client необходимо подключить к нашей ОС как виртуальное устройство. Windows не видит старые устройства, у которых нет поддержки технологии Plug-and-Play. Чтобы добавить для них драйверы, нужно использовать утилиту ручной настройки «Мастер установки оборудования».
Для этого необходимо:
- Зайти в диспетчер устройств → Действие → Установить старое устройство.
- Выбрать пункт с ручной установкой оборудования и вместо конкретного типа оборудования выбрать пункт Показать все устройства. Далее выбираем Установить с диска и выбираем USBIPEnum.Inf файл из распакованного архива.
- Мастер установки распознает оборудование USB/IP Enumerator, его и устанавливаем.
После этого в диспетчере устройств в системных устройствах мы увидим установленный и подписанный драйвер USB/IP Enumerator.
Проверяем доступные для подключения USB-устройства:
C:\Users\usbip usbip -l 188.124.55.21
1-1: Alcor Micro Corp. : Transcend JetFlash Flash Drive (058f:6387)
: /sys/devices/pci0000:00/0000:00:14.0/usb1/1-1
: (Defined at Interface level) (00/00/00)
: 0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
где 1-1 – BusID удаленного девайса.
Подключаем девайс к системе:
C:\Users\usbip usbip -a 188.124.55.21 1-1
new usb device attached to usbvbus port 1
Автоматизация клиента и сервера
Каждый раз прописывать команды и организовывать связность устройств вручную как минимум муторно. Как максимум — невозможно: например, если конечный клиент — простой обыватель, не подозревающий о существовании подобной «магии». Поэтому в дополнение к классическому пробросу USB-ключа нам также стоит автоматизировать этот процесс и на стороне клиента, и на стороне сервера.
Рассмотрим, как реализовать это на практике.
Автоматизация серверной части
Аналогично разделу с базовой настройкой сервера необходимо добавить модули в автозапуск, без этого никуда:
root@Descartes:~# vi /etc/modules
usbip-core
usbip-host
vhci-hcd
Далее создаем юнит в systemd, который будет обращаться к скрипту usbipd и расшаривать наш USB-девайс автоматически после старта сетевых служб ОС:
root@Descartes:~# vi /etc/systemd/system/usbipd.service
[Unit]
Description=USBIPd
After=network.target
[Service]
ExecStart=/bin/sh /root/script/usbipd
Type=oneshot
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Обновляем конфигурацию systemd и добавляем юнит в автозапуск:
root@Descartes:~#systemctl daemon-reload
root@Descartes:~#systemctl enable usbipd
После чего создаем сам скрипт автообновления инструментов и расшаривания устройства usbipd:
root@Descartes:~# vi /scripts/usbipd
#!/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
bindID='1-1' # BusID нашего USB-устройства на сервере
kernel_version=$(uname -r) - # создание переменной, содержащей текущую версию ядра системы
apt install linux-tools-$kernel_version # установка инструментов проброса для актуальной версии ядра
usbipd -D
sleep 1
usbip bind -b $bindID # делаем USB-устройство на сервере доступным для проброса
usbip attach --remote=localhost --busid=$bindID
sleep 3
usbip detach --port=00
Выдаем разрешение на запуск скрипта:
root@Descartes:~# chmod ugo+x usbipd
Последние три строки скрипта вынесены отдельно неслучайно. ПО на стороне сервера может работать неидеально. Иногда при попытке подключения устройства к клиенту под управлением ОС Windows может возникнуть проблема, когда клиент попросту не видит на сервере устройства с BusID 1-1:
usbip -a 188.124.55.21 1-1
usbip err: usbip_windows.c: 829 (attach_device) cannot find device
Проблема решается путем проброса USB-девайса сервера самому себе с его последующим отключением, что и содержится в последних трех строках скрипта.
Как можно было заметить, значения параметров BindID и port в скрипте являются статичными. Это связано с тем, что сервер изначально настраивается на проброс одного единственного USB-устройства, который будет получать одни и те же значения описанных выше параметров.
Автоматизация клиентской части (Windows)
Автоматизацию клиентской машины под управлением Windows мы осуществим за счет создания исполнительного bat-файла и планировщика заданий, который будет этот файл выполнять при запуске системы. В bat-файл добавляем инструкции, необходимые для подключения:
cd C:\Users\Makson\Desktop\usbip
usbip.exe -a 188.124.55.21 1-1
Запускаем планировщик заданий, где указываем следующие параметры:
- во вкладке Общие ставим галочку Выполнять с наивысшим приоритетом,
- во вкладке Триггеры указываем При запуске (либо любой другой),
- во вкладке Действия указываем путь до нашего bat-файла. В моем случае это C:\Users\Makson\Desktop\usbip\script.bat,
- во вкладке Условия снимаем галочку с пункта Останавливать задачу, выполняемую дольше.
Остальные настройки можно оставить по умолчанию.
Сохраняем, находим созданную задачу и выполняем ее ручной запуск для проверки работоспособности.
Автоматизация клиентской части (Linux)
Аналогично серверу создаем новый юнит для запуска автоматического подключения USB-устройства:
root@Descartes:~# vi /etc/systemd/system/usbip_client.service
[Unit]
Description=usbip_client
After=network.target
[Service]
ExecStart=/bin/sh /root/script/usbip_client
Type=oneshot
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Создаем скрипт подключения:
root@Descartes:~# vi /root/script/usbip_client
#!/bin/sh
apt-get install linux-tools-`uname -r` -y
sleep 1
usbip attach --remote=188.124.55.21 --busid=1-1
sleep 1
echo "Подключенные устройства:"
usbip port
Даем разрешение на запуск скрипта:
root@Descartes:~# chmod ugo+x usbip_client
Обновляем конфигурацию systemd и добавляем юнит в автозапуск:
root@Descartes:~#systemctl daemon-reload
root@Descartes:~#systemctl enable usbip_client
Как USBIP в очередной раз «спас мир»
Удаленный доступ к USB-устройствам по сети продолжает решать многие задачи в мире IT. Это может быть организация доступа к камере видеонаблюдения в серверной стойке современного дата-центра, где, как правило, запрещено размещать собственные точки Wi-Fi. Или же настройка удаленного доступа к аппаратным USB-ключам с дорогостоящими лицензиями проприетарного ПО, что защищает их от физического воздействия человека (поломки, утери и т.д.).
Методы, описанные в тексте, позволяют использовать USB-устройства без лишних рисков и затрат на обслуживание, а также выполнять задачи, где нет альтернативных решений.
Комментарии (10)
volkanin
31.05.2022 14:18+3А что за пакет usbip-client ? Откуда он взялся и как его можно собрать самому?
Makson_Herson Автор
31.05.2022 15:36Свободно распространяемый пакет от USB/IP Project.
как его можно собрать самому
Не задавался таким вопросом. Это скорее тема для отдельной статьи :)
alexandersusanin88
01.06.2022 10:02+2Полезная штука, на предыдущем месте работы так пробрасывали единственный живой usb ключ от ПО которое уже не поддерживалось вендор-лиз и купить новые ключи было нельзя, а оставшийся перепаивали уже не раз. Правда сервером выступал роутер с openwrt.
enamchuk
01.06.2022 10:34+2А как дела с безопасностью, разграничением прав доступа?
Если дополнительно не настраивать файрволл, кто угодно сможет подключиться к нашему устройству (о чём в статье нет упоминания).
Есть ли возможность авторизации или управление доступом в самом сервисе?
Worky
Автор! Насколько эта технология устойчива к обрывам связи? нет ли подвисаний клиента в случае обрыва связи к серверу? Опишите такие ситуации. Или вот ситуация, когда связь с потерями.
13werwolf13
отвечу за автора:
для hasp ключей подходит прекрастно, ибо только чтение и токену плевать на то завершилось оно удачно или нет.
а вот со флешками, принтерами, etc бывают проблемы, некоторые принтеры HP если в процессе передачи данных мигнула сеть нужно идти и обесточивать на секунд 10 чтобы он забыл о неудаче и начал работать, ну а побить ФС на флешке из-за плохого wi-fi вообще не удивительно.
Kenoby
Поддерживаю. У меня так USB ключ защиты 1с работает последние 2-3 года. Клиент удаленный виндовый сервер. на котором в шедулере запущен usbip.exe, если связь теряется приложение вылетает и перезапускается по расписанию в течение 10 минут. Этого более чем достаточно для 1с сервера чтобы не потерять лицензию. А вот для клиентских лицензий 1с проще проставить hasp lm server (конечно если есть IP связанность).
Makson_Herson Автор
На отказоустойчивость тестировать не пробовал. Обычно если что то и может пойти не так. то в момент подключения самого устройства.
Если клиент подвисает, то девайс просто отключится. Чем это может быть чревато: если "не безопасно" отсоединить устройство, то сервер может думать, что устройство все еще пробрасывается и сходу не дать подключить его заново.