USB/IP — sing-box
Two services share USB devices over USB/IP: usbip-server exports local devices, and usbip-client imports devices from a remote server. Both are built on sing-usbip, which adds enhancements such as hotplug on top of the standard protocol while staying interoperable with it: a standard USB/IP client can import from usbip-server, but usbip-client needs a sing-box (sing-usbip) server.
Server — usbip-server
type: "usbip-server" under services[]:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
provider | string | default | default | dynamic | Where exported devices come from. default exports the local devices matched by devices (CLI on Linux, Windows and macOS only, with elevated privileges). dynamic takes devices at runtime from a sing-box API client instead — the graphical clients on macOS and Android, or the sing-box Dashboard in a Chromium-based browser. |
Source: option/usbip.go:17-21 · pinned at v1.14.2 (af6e64c)
The server also embeds ListenOptions (see Inbounds); listen_port defaults to 3240, the standard USB/IP port. With provider: "default" it takes:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
devices | []USBIPDeviceMatch | (required) | [USBIPDeviceMatch] | Which local devices to export. Required with the default provider. |
Source: option/usbip.go:77-79 · pinned at v1.14.2 (af6e64c)
The dynamic provider has no extra fields.
Device match
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
bus_id | string | (any) | <bus-port> | USB bus ID, e.g. 1-2. |
vendor_id | uint16 | (any) | <uint16> | USB vendor ID as a JSON number (decimal — e.g. 1133 for 0x046d). |
product_id | uint16 | (any) | <uint16> | USB product ID as a JSON number. |
serial | string | (any) | <string> | Device serial number. |
Source: option/usbip.go:70-75 · pinned at v1.14.2 (af6e64c)
Every field set in one object must match; several objects are combined as a union. Each object needs at least one field.
Client — usbip-client
type: "usbip-client" under services[]:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
server | string | (required) | <host> | Address of the remote usbip-server. |
server_port | uint16 | 3240 | <port> | Port of the remote usbip-server. |
Source: option/outbound.go:183-186 · pinned at v1.14.2 (af6e64c)
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
devices | []USBIPDeviceMatch | (all exported) | [USBIPDeviceMatch] | Which remote devices to import, using the same match objects as the server. Empty imports every exported device. |
Source: option/usbip.go:64-68 · pinned at v1.14.2 (af6e64c)
The client embeds the dial fields (see Outbounds), but only detour takes effect.
Minimal example
Server exporting a keyboard by vendor/product ID plus whatever is plugged into bus port 1-2:
{
"services": [
{
"type": "usbip-server",
"tag": "usb-share",
"listen": "0.0.0.0",
"devices": [
{ "vendor_id": 1133, "product_id": 49948 },
{ "bus_id": "1-2" }
]
}
]
}Client importing only the device on bus port 1-2:
{
"services": [
{
"type": "usbip-client",
"tag": "usb-remote",
"server": "192.0.2.10",
"devices": [{ "bus_id": "1-2" }]
}
]
}Notes
- Requires the
with_usbipbuild tag and is only built for Linux, Windows and macOS with CGO. Elsewhere (including iOS) both types exist but fail at startup with "USB/IP is not included in this build". provider: "default"only works when sing-box runs directly from the CLI, and needs elevated privileges; exporting on macOS additionally requires disabling System Integrity Protection.- With
provider: "dynamic", devices are shared at runtime through the API service — from the graphical clients, the Dashboard, or thesing-box apicommand. - Standard USB/IP has no encryption or authentication, and neither service has credential fields. Expose
usbip-serveronly on trusted networks, or reach it through a tunnel via the client'sdetour.
Cross-core notes
- Neither Xray-core nor mihomo has a USB/IP equivalent.
Source: option/usbip.go:17-81 · v1.14.2 (af6e64c)
