Skip to content

abilisoft/usbip-go

usbip-go

CI CodeQL Trivy OpenSSF Scorecard OpenSSF Best Practices codecov Go Report Card License: Apache-2.0

Pure-Go reimplementation of USB/IP userspace for Linux. Ships three artefacts from a single code base:

  • pkg/usbip — embeddable library for importers (client) and exporters (server).
  • usbip-go — operator/client CLI (cobra + jsonlines).
  • usbipd-go — production daemon with socket activation, Prometheus metrics, status UDS, and graceful drain.

No cgo, no dependencies on usbip-utils. Upstream wire compatibility is pinned by conformance tests against real captures.

How this compares to upstream usbip-utils

The upstream reference is the C client/daemon shipped under linux/tools/usb/usbip (built and packaged as usbip / usbipd / libusbip). usbip-go re-uses the same wire format and the same kernel sysfs interface, so it interoperates with upstream peers in either direction. What differs is the userspace surface around the protocol:

Capability upstream usbip-utils usbip-go
Wire-compatible with usbip-utils peers
Uses kernel vhci_hcd / usbip_host / usbip_vudc
Pure Go, no cgo
Cross-compile to all Linux arches in one command
Embeddable as a library (pkg/usbip)
Auto-reconnect on detach (exponential backoff + jitter)
Concurrent-attach deduplication (per (remote, busid))
Per-attach MaxAttempts / OnReconnect callback
Graceful drain + bounded ShutdownTimeout
Structured logging (slog JSON / text)
Prometheus metrics on importer + exporter
Event subscription API (port / session / reconnect)
systemd socket activation (usbipd-go.socket)
Status UDS for live introspection
JSON output mode with versioned schema
Allow-list CIDR / rate-limit / session caps
TCP_NODELAY on dialed connections
Configurable connect timeout
Tunable TCP keepalive (idle / interval / probes)
Tunable SO_SNDBUF / SO_RCVBUF for WAN bandwidth-delay
Static read / write deadlines per Importer / Exporter
Tolerance for high-latency / lossy links (50–800 ms RTT)
Reproducible builds (-trimpath, no cgo)
Static analysis + vuln scanning (CodeQL, golangci-lint, govulncheck, Trivy)
Conformance tests against real wire captures
Fuzz targets on the wire codec
Mutation testing on protocol-critical packages
Coverage gate (90%+ for pure-logic packages)
SBOM + cosign keyless signed releases
SLSA Build Provenance on every release
OpenSSF Scorecard / Best Practices
TLS or authentication on the wire (out of scope — tunnel via WG/SSH/Tailscale)

The underlying invariant — wire-compatible with upstream — does not change as new features land.

Security posture

USB/IP is a plaintext, unauthenticated protocol.

Anyone who can TCP-connect to port 3240 can list exported devices and attach them. usbip-go does not wrap the wire in TLS — TLS is out of scope (see docs/security.md). Deploy only over already-trusted networks: private LAN, Wireguard, Tailscale, or SSH tunnels. Never expose port 3240 on the public internet.

The daemon ships defence-in-depth flags — --allow-cidr, --max-sessions, --accept-rate-limit — but these are enforcement seams, not authentication. Read docs/security.md before deploying.

Install

Release binaries

Prebuilt binaries, .deb, and .rpm packages are published to GitHub Releases.

VERSION=1.0.0  # replace with the tag you want; see the Releases page
curl -LO "https://github.com/abilisoft/usbip-go/releases/download/v${VERSION}/usbip-go_${VERSION}_linux_amd64.tar.gz"
tar xzf "usbip-go_${VERSION}_linux_amd64.tar.gz"
sudo install -m 0755 usbip-go usbipd-go /usr/bin/

GoReleaser archive names follow usbip-go_<version>_<os>_<arch>.tar.gz (see .goreleaser.yml). Pick the architecture that matches your host (amd64, arm64, or armv7).

Verifying a release

Every release ships a SLSA Build Provenance bundle (multiple.intoto.jsonl) and a cosign keyless signature on the checksums file (Sigstore bundle format). Verify both before installing — name_template in .goreleaser.yml produces the checksum filename as usbip-go_<version>_checksums.txt, so the matching cosign bundle is usbip-go_<version>_checksums.txt.sigstore.json:

VERSION=1.0.0
ARCHIVE=usbip-go_${VERSION}_linux_amd64.tar.gz
CHECKSUMS=usbip-go_${VERSION}_checksums.txt
BUNDLE=${CHECKSUMS}.sigstore.json
BASE=https://github.com/abilisoft/usbip-go/releases/download/v${VERSION}

curl -LO "${BASE}/${ARCHIVE}"
curl -LO "${BASE}/${CHECKSUMS}"
curl -LO "${BASE}/${BUNDLE}"
curl -LO "${BASE}/multiple.intoto.jsonl"

# 1. Provenance: prove the artifact came out of the abilisoft/usbip-go
#    GitHub Actions release workflow at the matching tag.
slsa-verifier verify-artifact "${ARCHIVE}" \
  --provenance-path multiple.intoto.jsonl \
  --source-uri github.com/abilisoft/usbip-go \
  --source-tag "v${VERSION}"

# 2. Checksum signature: prove the checksums file was signed by a
#    Sigstore keyless cert whose OIDC subject is the
#    .github/workflows/release.yml workflow at the same v*.*.* tag —
#    matches the exact workflow path so a different workflow in this
#    repo cannot satisfy the check. The Sigstore bundle (--bundle)
#    carries the leaf certificate, the signature, and the rekor
#    inclusion proof in a single file.
cosign verify-blob \
  --bundle "${BUNDLE}" \
  --certificate-identity-regexp '^https://github\.com/abilisoft/usbip-go/\.github/workflows/release\.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  "${CHECKSUMS}"

# 3. Per-binary integrity: confirm the archive's sha256 is in the
#    checksums file.
sha256sum -c --ignore-missing "${CHECKSUMS}"

Install slsa-verifier and cosign once; both are statically linked single binaries.

Systemd

The release archive and packages both include systemd units. Drop them in place and enable the socket unit:

sudo install -Dm 0644 contrib/systemd/usbipd-go.service /etc/systemd/system/usbipd-go.service
sudo install -Dm 0644 contrib/systemd/usbipd-go.socket  /etc/systemd/system/usbipd-go.socket
sudo systemctl daemon-reload
sudo systemctl enable --now usbipd-go.socket

Socket activation means the daemon starts on the first inbound connection. See docs/ops.md for the full systemd hardening recipe, metrics wiring, and drain procedure.

go install

go install github.com/abilisoft/usbip-go/cmd/usbip-go@latest
go install github.com/abilisoft/usbip-go/cmd/usbipd-go@latest

Requires Go 1.26 or newer.

Kernel modules

Every host running usbipd-go (exporter) or the usbip-go client needs the relevant kernel modules:

sudo modprobe usbip_core vhci-hcd usbip-host
echo -e 'usbip_core\nvhci_hcd\nusbip_host' \
  | sudo tee /etc/modules-load.d/usbip-go.conf

Quickstart

1. Embed the library

package main

import (
    "context"
    "log/slog"

    "github.com/abilisoft/usbip-go/pkg/domain"
    "github.com/abilisoft/usbip-go/pkg/usbip"
)

func main() {
    imp, _ := usbip.NewImporter(usbip.WithImporterLogger(slog.Default()))
    defer imp.Close()

    remote, _ := domain.ParseRemote("10.0.0.5:3240")
    busid, _ := domain.ParseBusID("1-1.2")

    port, _ := imp.Attach(context.Background(), remote, busid, usbip.AttachOptions{
        AutoReconnect: true,
    })
    _ = port // detach later with imp.Detach(ctx, port.ID)
}

More patterns under examples/ — client, server, events, reconnect, metrics.

2. CLI attach

sudo usbip-go attach 10.0.0.5 1-1.2
sudo usbip-go port
sudo usbip-go detach 0

3. Daemon via systemd

sudo systemctl enable --now usbipd-go.socket
sudo usbip-go bind 1-1.2           # export a local device
sudo systemctl status usbipd-go

Metrics, drain, and readiness endpoints are in docs/ops.md.

Development

The dev toolchain is hermetic: the only host-side prerequisites are Docker and Task. Go, linters, formatters, and every release tool (goreleaser, syft, cosign, nfpm, git-cliff) are pinned in flake.nix and delivered through a Nix container — task setup seeds the store once, then task test, task lint, and friends reuse it.

See CONTRIBUTING.md for the full onboarding flow, the hermetic-cache layout under ./build/, and the microVM path that runs integration tests against a real Linux kernel without requiring the USBIP modules on your host.

Documentation

Status

v1 surface is under active development. APIs under pkg/usbip and pkg/domain are guarded by apidiff baselines and require a BREAKING: commit for any incompatible change — see CONTRIBUTING.md.

License

Apache-2.0. See LICENSE.

About

Pure-Go reimplementation of USB/IP userspace for Linux

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors