Укротяваме 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 проект. Привлекателен е с откритостта си, особено след като хората от ReactOS подписаха им драйвера за Windows, така че сега дори и на x64 всичко работи без никакви заобикалки като тестов режим. За което голямо благодаря на екипа на ReactOS! Звучи всичко красиво, ще опитаме да видим дали това е истината? За съжаление, самият проект също е натрупал забавяния, и не можем да разчитаме на поддръжка — но къде сме ние, винаги можем да се справим, кодът е наличен!

Част втора, свързана със сървърите и Linux

Сървърът USB/IP, който споделя USB устройства през мрежата, може да бъде инсталиран само в Linux-базирани операционни системи. Е, какво да правим, инсталираме на виртуалка 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:

sudo usbipd -D

Следващото, глобалният разум ни подсказва, че заедно с usbip идват скриптове, които ни позволяват да управляваме сървъра — да покажем кое устройство ще бъде споделено в мрежата, да видим статуса и т.н. Тук ни очаква още един инструмент — тези скриптове в версия 0.2.x, отново, са преименувани. Получаваме списък с команди с помощта на

sudo usbip

Чета описанието на командите и става ясно, че за да споделим необходимото 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

usbipd -D

Част трета, клиентска и заплетена

Пробвах да свържа споделеното устройство в мрежата към машина с Debian веднага на същия сървър и всичко се свърза прекрасно:

sudo usbip attach --remote=localhost --busid=1-1

Преминаваме на Windows. В моя случай това беше Windows Server 2008R2 Standard Edition. Официалното ръководство иска първо да инсталираме драйвера. Процедурата е отлично описана в приложеното към windows-клиента readme, правим всичко както е написано, всичко става. Работи и на XP без никакви трудности.

Разопаковайки клиента, опитваме да монтираме нашия ключ:

C:Program FilesUSB-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) не може да намери устройството

Ой-ой. Нещо не е наред. Използваме умението на Google. Срещат се разпръснати споменавания, че нещо не е наред с константите, в сървърната част разработчиците промениха версията на протокола при преминаването на версия 0.2.0, а в клиента под Win забравили да го направят. Предложението е — сменете константата в изходния код и пререблете клиента.

Но наистина не ми се иска да изтеглям Visual Studio за тази процедура. Затова имам стария добър Hiew. В изходния код константата е обявена като двойно число. Нека потърсим в файла 0x00000106, заменяйки с 0x00000111. Не забравяйте, редът на байтовете е обратен. Резултатът — две съвпадения, патчваме:

[usbip.exe]
00000CBC: 06 11
00000E0A: 06 11

Ииии… да!

C:Program FilesUSB-IP>usbip -a %server-ip% 1-1
нов USB устройство прикрепено към usbvbus порт 1

На това можеше да се приключи изложението, но музиката не игра дълго. След като рестартирах сървъра, открих, че устройството на клиента не се монтира!

C:Program FilesUSB-IP>usbip -a %server-ip% 1-1
usbip err: usbip_windows.c: 829 (attach_device) не може да намери устройството

И всичко. На това дори всезнаещият Google не можа да ми отговори. А междувременно, командата за показване на наличните устройства на сървъра показва напълно коректно — ето го, ключа, можете да го монтирате. Опитвам да монтирам от Linux — работи! А ако сега опитаме от Windows? О ужас — това работи!

Последни проблеми: нещо в кода на сървъра не е дописано. При споделяне на устройството, той не чете броя на USB дескрипторите. А при монтиране на устройството от Linux, това поле се попълва. За съжаление, с разработката под Linux съм запознат на ниво „make && make install“. Затова проблемът беше решен с доста груб хакинг — добавяне в /etc/rc.local

usbip attach --remote=localhost --busid=1-1
usbip port
usbip detach --port=00

Заключителна част

След някои перипетии, това работи. Желаното е постигнато, сега ключът може да бъде монтиран на всяко ПК (и да бъде демонтиран, разбира се), включително и извън广播 сигнала в мрежата. Ако желаете, можете да го направите с помощта на скрипт за команден ред. Както е приятно - удоволствието е напълно безплатно.
Надявам се опитът ми да помогне на хабражителите да избегнат онези грабли, които оставиха следа на челото ми. Благодаря за вниманието!

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster