Укрощаем USB/IP
Регулярно возникает задача подключения USB-устройства к удаленному ПК через локальную сеть. Под катом изложена история моих поисков в этом направлении, и путь к готовому решению на базе open-source проекта USB/IP с описанием заботливо установленных различными людьми на этом пути препятствий, а также способов их обхода.
Часть первая, историческая
Если машина виртуальная — всё это несложно. Функционал проброса USB от хоста в виртуалку появился еще в VMWare 4.1. Но в моём случае ключик защиты, опознающийся как WIBU-KEY, нужно было в разное время подключать к разным машинам, и не только виртуальным.
Первый виток поиска в далеком 2009-м году привел меня к железке под названием TrendNet TU2-NU4
Плюсы:
- работает не всегда. Допустим, ключ защиты Guardant Stealth II через неё не заводится, ругаясь ошибкой «устройство не может быть запущено».
- ПО для управления (читай — монтирования и размонтирования USB-устройств) убого до крайности. Ключи командной строки, автоматизация — не, не слышали. Всё только руками. Кошмар.
- управляющее ПО ищет саму железку в сети широковещанием, поэтому работает это только в пределах одного broadcast-сегмента сети. Указать IP-адрес железки руками нельзя. Железка в другой подсети? Тогда у вас проблема.
- разработчики забили на устройство, слать баг-репорты бесполезно.
Часть вторая, серверно-линуксовая
Сервер USB/IP, расшаривающий USB-девайсы по сети, может быть поднят только в Linux-based OS. Ну что ж, линукс так линукс, устанавливаем на виртуалку Debian 8 в минимальной конфигурации, стандартное движение руками:
sudo apt-get update sudo apt-get upgrade sudo apt-get install usbip
Установились. Дальше интернет подсказывает, что нужно бы загрузить модуль usbip, но — здравствуйте, первые грабли. Нет такого модуля. А всё оттого, что большинство руководств в сети относятся к более старой ветке 0.1.x, а в крайней 0.2.0 модули usbip имеют другие названия.
sudo modprobe usbip-core sudo modprobe usbip-host sudo lsmod | grep usbip
Ну и добавим в /etc/modules такие строки, чтобы загружать их автоматически при старте системы:
usbip-core usbip-host vhci-hcd
Дальше всемирный разум нам подсказывает, что в комплекте с usbip идут скрипты, позволяющие нам управлять сервером — показать, какое устройство он будет расшаривать по сети, посмотреть статус, и так далее. Тут нас поджидает еще один садовый инструмент — эти скрипты в ветке 0.2.x, опять же, переименованы. Получить список команд можно с помощью
Почитав описание команд, становится понятно, что для того, чтобы расшарить требуемый USB-девайс, usbip хочет узнать его Bus ID. Уважаемые зрители, на арене грабли номер три: тот Bus ID, который выдаст нам lsusb (казалось бы, самый очевидный путь) — ей не подходит! Дело в том, что железки вроде USB-хабов usbip игнорирует. Поэтому, воспользуемся встроенной командой:
user@usb-server:~$ sudo usbip list -l - busid 1-1 (064f:0bd7) WIBU-Systems AG : BOX/U (064f:0bd7)
Примечание: здесь и далее в листингах я буду всё описывать на примере моего конкретного USB-ключа. Ваши название железки и пара VID:PID могут и будут отличаться. Моя называется Wibu-Systems AG: BOX/U, VID 064F, PID 0BD7.
Теперь мы можем расшарить наше устройство:
user@usb-server:~$ sudo usbip bind --busid=1-1 usbip: info: bind device on busid 1-1: complete
user@usb-server:~$ sudo usbip list -r localhost Exportable USB devices ====================== - localhost 1-1: WIBU-Systems AG : BOX/U (064f:0bd7) : /sys/devices/pci0000:00/0000:00:11.0/0000:02:00.0/usb1/1-1 : Vendor Specific Class / unknown subclass / unknown protocol (ff/00/ff)
Троекратное ура, товарищи! Сервер расшарил железку по сети, и мы можем её подключать! Осталось только дописать автозапуск демона usbip в /etc/rc.local
Часть третья, клиентская и запутанная
Подключить расшаренное устройство по сети к машине под управлением Debian я попробовал сразу же на том же сервере, и всё прекрасно подключилось:
sudo usbip attach --remote=localhost --busid=1-1
Переходим к Windows. В моем случае это был Windows Server 2008R2 Standard Edition. Официальное руководство просит сначала установить драйвер. Процедура прекрасно описана в прилагаемом к windows-клиенту readme, делаем всё как написано, всё получается. На XP тоже работает без каких-либо трудностей.
Распаковав клиент, пробуем примонтировать наш ключик:
C:\Program Files\USB-IP>usbip -a %server-ip% 1-1 usbip err: usbip_network.c: 121 (usbip_recv_op_common) recv op_common, -1 usbip err: usbip_windows.c: 756 (query_interface0) recv op_common usbip err: usbip_windows.c: 829 (attach_device) cannot find device
Ой-ой. Что-то пошло не так. Используем навык гугла. Встречаются отрывочные упоминания, что что-то там не так с константами, в серверной части разработчики при переходе на версию 0.2.0 изменили версию протокола, а вот в клиенте под Win сделать это забыли. Предлагаемое решение — поменяйте константу в исходнике и пересоберите клиент.
Вот только очень мне не хочется качать Visual Studio ради этой процедуры. Зато у меня есть старый-добрый Hiew. В исходнике константа объявлена как двойное слово. Поищем в файле 0х00000106, заменяя на 0х00000111. Не забываем, порядок байт обратный. Итог — два совпадения, патчим:
[usbip.exe] 00000CBC: 06 11 00000E0A: 06 11
C:\Program Files\USB-IP>usbip -a %server-ip% 1-1 new usb device attached to usbvbus port 1
На этом можно было бы закончить изложение, но музыка играла недолго. Перезагрузив сервер, я обнаружил, что устройство на клиенте не монтируется!
C:\Program Files\USB-IP>usbip -a %server-ip% 1-1 usbip err: usbip_windows.c: 829 (attach_device) cannot find device
И всё. На это мне не смог ответить даже всезнающий гугл. А при этом команда отобразить доступные на сервере устройства вполне корректно показывает — вот он, ключ, можете монтировать. Пробую примонтировать из-под Linux — работает! А если теперь попробовать из-под Windows? О ужас — это работает!
Грабли последние: что-то там в коде сервера не дописано. При расшаривании устройства он не считывает с него количество USB-дескрипторов. А при монтировании устройства из-под Linux, это поле заполняется. К сожалению, с разработкой под Linux я знаком на уровне «make && make install». Поэтому проблема решена с помощью довольно грязного хака — добавлением в /etc/rc.local
usbip attach --remote=localhost --busid=1-1 usbip port usbip detach --port=00
Часть заключительная
После некоторых мытарств, это работает. Желаемое получено, теперь ключ можно примонтировать к любому ПК (и размонтировать, конечно же, тоже), в том числе — за пределами широковещательного сегмента сети. Если хочется — можно это сделать с помощью скрипта командной оболочки. Что приятно — удовольствие абсолютно бесплатное.
Надеюсь, что мой опыт поможет хабражителям обойти те грабли, которые отпечатались у меня на лбу. Спасибо за внимание!
Linux сервер на usb-флэшке
В интернете много мануалов о том, как правильно поставить линукс на флэшку, чтобы она не померла (отключить журнал, noatime, ramfs etc). Но неужели нет готового образа, где все уже настроено?
- Сервер HP MicroServer Gen8.
- В нем есть один жесткий диск (btrfs).
- На флэшке стоит Rockstor.
- После перезагрузки rockstor не всегда поднимается корректно (не монтирует разделы, не запускает некоторые docker-контейнеры).
- Демо-лицензия на ilo закончилась, а если система с флэшки ip не получила, то нет ssh — приходится помучиться, чтобы все оживить.
- Простую систему, которая получает ip по dhcp поднимает ssh.
- ФС флэшки вообще можно ro монтировать, когда она в сервер воткнута, чтобы не думать о ее скорой кончине. Если нужны какие-то доп-настройки — переткнул в комп и поправил.
- Система на фэлешке монтирует btrfs разделы с основного жесткого диска и запускает docker-контейнеры (можно будет bash-скриптами запилить).
Пока писал, подумал: а CoreOS мне не подойдет. (UPD: СoreOS больше 4 гигов весит, слишком жирный).
ramfs это не то что бы против износа флешки, это прежде всего ускорение, особенно если usb 2.0. Да и так обычные флешки не особо быстро читаются.
Но в целом это какая-то дичь грузить сервер с флешки, особенно если в нём есть винт. По идее с такими требованиями вам нужно искать среди дистров для маршрутизаторов.
Но в целом это какая-то дичь грузить сервер с флешки, особенно если в нём есть винт.
Суть в том, что после того, как сервер загрузился, читать с rootfs больше не нужно же. А если произошел какой-то сбой — перезалил образ на флэшку и все снова работает. А вот поставить систему заново на винт — это уже не очень удобно (сервер в труднодоступном месте, монитора клавиатуры у него нет, ilo без лицензии не дает виртуальной консоли).
Rockstor неплохо работает, но иногда глючит. Поэтому хочется простого линукса + баш-скриптов написать под мои простые нужды (transmission и plex).
Держать в сервере флешку с каким-нибудь Линуксом для восстановления/установки основной системы это одно, ЕМНИП iLO и без лицензии позволяет выбрать порядок загрузки.
Держать же ядро, dhcp клиента и sshd это другое, их же обновлять надо. Но в общем то дело ваше, я просто рассуждаю на тему, «почему нет готового образа, где всё такое уже настроено».
Хорошо, скажу немного по другому. Я не могу установить систему на сам сервер: нет монитора и клавиатуры, а remote console в ilo без лицензии не работает. Поэтому мне нужна система на флэшке, которая загрузится и даст ssh.
Судя по тому, что вы говорите, это вполне себе обычная задача, чтобы починить основную систему. Так что такие системы должны быть готовые.
чтобы она не померла (отключить журнал, noatime, ramfs etc)
А почему и на флешку btrfs не поставишь?
У меня на ней без всяких таких жертв давно живёт домашний компьютер, ну понятно что флешка должна быть очень хорошая.
Дебиан можно поставить по ssh, емнип
aol ★★★★★ ( 28.01.18 19:58:05 MSK )
Последнее исправление: aol 28.01.18 19:59:19 MSK (всего исправлений: 1)
Опять же — есть маны о том, как переделать образ netinst (или свой собрать), чтобы сразу ssh был. Но почему-то нет простого готового образа.