Categories
SysOps

How to share USB device over network

Share USB device over network using usbip utility.

Preliminary notes

The following example is based on Ubuntu 21.10 using 5.13.0-27-generic #29-Ubuntu SMP Wed Jan 12 17:36:47 UTC 2022 kernel.

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 21.10
Release:	21.10
Codename:	impish
$ uname -a
Linux milosz-IdeaCentre-5-14IOB6 5.13.0-27-generic #29-Ubuntu SMP Wed Jan 12 17:36:47 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Common steps

Install linux-tools-common package as it contains usbip utility.

$ sudo apt install linux-tools-common

Determine if all dependencies are installed.

$ usbip version
WARNING: usbip not found for kernel 5.13.0-27

  You may need to install the following packages for this specific kernel:
    linux-tools-5.13.0-27-generic
    linux-cloud-tools-5.13.0-27-generic

  You may also want to install one of the following packages to keep up to date:
    linux-tools-generic
    linux-cloud-tools-generic

Install missing dependencies.

$ sudo apt install linux-tools-generic linux-cloud-tools-generic

Fix missing list of USB ID’s.

$ sudo mkdir  /usr/share/hwdata
$ sudo ln -s /usr/share/misc/usb.ids /usr/share/hwdata/usb.ids

Ensure that required modules will load at boot.

$ cat <<EOF | sudo tee /etc/modules-load.d/usbip.conf
usbip_core
usbip_host
vhci_hcd
EOF

Restart systemd-modules-load service to load these modules without reboot.

$ sudo systemctl restart systemd-modules-load.service

Ensure that usbip utility can be executed.

$ usbip version
usbip (usbip-utils 2.0)

Configure server

Create systemd service for USB/IP server daemon.

$ cat <<EOF | sudo tee /etc/systemd/system/usbipd.service
[Unit]
Description=USB/IP server daemon
After=network.target


[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/usbipd

[Install]
WantedBy=multi-user.target
EOF

Create a template service for binding targets.

$ cat <<EOF | sudo tee /etc/systemd/system/usbip-bind@.service
[Unit]
Description=USB/IP server 
After=network.target usbipd.service
Requires=usbipd.service

[Service]
Type=simple
ExecStart=/usr/bin/usbip bind --busid %i
ExecStop=/usr/bin/usbip unbind --busid %i
RemainAfterExit=yes
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

Reload systemd manager configuration.

$ sudo systemctl daemon-reload

USB/IP server daemon is disabled by default.

$ systemctl status usbipd.service 
○ usbipd.service - USB/IP server daemon
     Loaded: loaded (/etc/systemd/system/usbipd.service; disabled; vendor preset: enabled)
     Active: inactive (dead)

Enable USB/IP server daemon service.

$ sudo systemctl enable --now usbipd.service 
Created symlink /etc/systemd/system/multi-user.target.wants/usbipd.service → /etc/systemd/system/usbipd.service.

Inspect USB/IP server daemon status.

$ systemctl status usbipd.service 
● usbipd.service - USB/IP server daemon
     Loaded: loaded (/etc/systemd/system/usbipd.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2022-01-23 14:49:02 CET; 1min 12s ago
   Main PID: 2281034 (usbipd)
      Tasks: 1 (limit: 18955)
     Memory: 332.0K
        CPU: 5ms
     CGroup: /system.slice/usbipd.service
             └─2281034 /usr/lib/linux-tools/5.13.0-25-generic/usbipd

sty 23 14:49:02 desktop systemd[1]: Started USB/IP server daemon.
sty 23 14:49:02 desktop usbipd[2281034]: usbipd: info: starting usbipd (usbip-utils 2.0)
sty 23 14:49:02 desktop usbipd[2281034]: usbipd: info: listening on 0.0.0.0:3240
sty 23 14:49:02 desktop usbipd[2281034]: usbipd: info: listening on :::3240

Display USB devices.

$ lsusb 
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 8087:8000 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 006: ID 1050:0407 Yubico.com Yubikey 4/5 OTP+U2F+CCID
Bus 001 Device 002: ID 8087:8008 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Display exportable USB devices.

$ usbip list --local
 - busid 1-1.6 (1050:0407)
   Yubico.com : Yubikey 4/5 OTP+U2F+CCID (1050:0407)

Display exportable USB devices using machine-friendly format.

$ usbip list --parsable --local
busid=1-1.6#usbid=1050:0407#

Bind a device using systemd template service.

$ sudo systemctl enable --now usbip-bind@1-1.6
Created symlink /etc/systemd/system/multi-user.target.wants/usbip-bind@1-1.6.service → /etc/systemd/system/usbip-bind@.service.

Inspect service status.

$ sudo systemctl status  usbip-bind@1-1.6
● usbip-bind@1-1.6.service - USB/IP server
     Loaded: loaded (/etc/systemd/system/usbip-bind@.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sun 2022-01-23 14:55:46 CET; 13s ago
    Process: 2282127 ExecStart=/usr/bin/usbip bind --busid 1-1.6 (code=exited, status=0/SUCCESS)
   Main PID: 2282127 (code=exited, status=0/SUCCESS)
        CPU: 4ms

sty 23 14:55:46 desktop systemd[1]: Started USB/IP server.
sty 23 14:55:46 desktop usbip[2282127]: usbip: info: bind device on busid 1-1.6: complete

Display exported USB devices.

$ usbip list --remote=localhost
Exportable USB devices
======================
 - localhost
      1-1.6: Yubico.com : Yubikey 4/5 OTP+U2F+CCID (1050:0407)
           : /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.6
           : (Defined at Interface level) (00/00/00)

Configure client

Display USB devices.

$ lsusb 
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller
Bus 001 Device 008: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 006: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 010: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Display USB devices exported on remote server.

$ usbip list --remote dell
Exportable USB devices
======================
 - dell
      1-1.6: Yubico.com : Yubikey 4/5 OTP+U2F+CCID (1050:0407)
           : /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.6
           : (Defined at Interface level) (00/00/00)

Attach specific device.

$ sudo usbip attach --remote dell --busid 1-1.6

Display attached devices.

$ sudo usbip port
Imported USB devices
====================
Port 00:  at Full Speed(12Mbps)
       Yubico.com : Yubikey 4/5 OTP+U2F+CCID (1050:0407)
       3-1 -> usbip://dell:3240/1-1.6
           -> remote bus/dev 001/006

Display USB devices.

$ lsusb 
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 1050:0407 Yubico.com Yubikey 4/5 OTP+U2F+CCID
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller
Bus 001 Device 008: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 006: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 010: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Use the device freely.

Detach device after using it.

$ sudo usbip detach --port 00
usbip: info: Port 0 is now detached!

Create a template service for atta.

$ cat <<EOF | sudo tee /etc/systemd/system/usbip-attach@.service
[Unit]
Description=USB/IP bind service 
After=network.target
Requires=usbipd.service

[Service]
Type=simple
ExecStart=/usr/bin/usbip bind --busid %i
ExecStop=/usr/bin/usbip unbind --busid %i
RemainAfterExit=yes
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

Reload systemd manager configuration.

$ sudo systemctl daemon-reload

Additional notes

Use firewall and create a whitelist on the server to protect USB/IP server daemon port on the local network/vpn.

The systemd template service for client can be created by using a dedicated environment file as a parameter, inside you can define remote server and USB bus id.

I am using it for simple input devices like Logitech unifying receiver and it works flawlessy.

The vhci_hcd module is required on the client side.