Skip to content

Repository files navigation

Switchboard

sb_demo.mp4

Switchboard manages Cisco switches from a web browser via netbird-wasm. There is no backend, Switchboard is able to communicate via SSH/gNMI/RESTCONF/HTTPS through a remote netbird peer.

Requirements

  • Node.js 20.19 or later, or 22.12 or later (Vite 7 needs one of these)
  • Go 1.25 or later, to build the protocol module
  • A NetBird setup key
  • A NetBird peer that routes to the switch

Install and run

  1. Install the dependencies:
    npm install
  2. Start the development server:
    npm run dev
  3. Open https://localhost:5173 in the browser.

First run

  1. Open /v2.
  2. Enter the NetBird setup key and the management URL. Then connect.
  3. Add a device. Give it a name and an IP address.
  4. Open the device.

Switchboard keeps the setup key and the device list in localStorage. It sends this data to no server.

The overlay connect panel and the device list

Management Tabs

The overview screen: device facts, the front panel, the interfaces table, and the port editor

The main screen provides a high-level overview of the switch and interfaces.

Terminal

An SSH session on the terminal screen

The terminal opens an SSH session to the switch.

Endpoints

The endpoint table, with MAC, IP, port, vendor, and LLDP neighbor

The endpoint tab joins the MAC table, the ARP table, and the LLDP neighbors.

Diagnostics

Cable diagnostics, reachability, and packet capture

The diagnostics tab runs three tools on the switch. Cable diagnostics (TDR) tests each pair. Reachability runs ping and traceroute. Packet capture creates a downloadable pcap.

Commands

Command What it does
npm run dev Start the development server on port 5173
npm run build Build the production files into build/
npm run preview Serve the production build
npm run check Run svelte-check
npm run build:protocol Rebuild the Go protocol module

Layout

Path Contents
src/routes/v2/ The current user interface
src/routes/switch/ The first prototype interface
src/lib/netbird/ The NetBird worker and its main-thread client
src/lib/protocol/ The protocol worker and its main-thread client
wasm-protocol/ Go source for the protocol module
scripts/build-protocol.sh Builds the protocol module to wasm-protocol/build/

How it works

Switchboard runs two WebAssembly modules, each in its own web worker.

Worker 1 runs the netbird-wasm SDK. It makes the browser tab a WireGuard peer on the overlay network, and it opens raw TCP and UDP sockets to the switch through remote NetBird peers.

Worker 2 runs switchboard's protocol module, under wasm-protocol/. This Go program speaks HTTPS for RESTCONF, SSH for the terminal, and gRPC for gNMI. It receives sockets from worker 1 through the SDK bridge, and treats each one as an ordinary net.Conn.

Each module is a separate program with its own Go runtime, and each runtime owns the thread that it runs on. Two workers therefore let the tunnel and the protocol work run at the same time, clear of the thread that draws the user interface.

flowchart LR
  subgraph tab["Browser tab"]
    direction TB
    main["Main thread<br/>user interface<br/>control plane"]
    subgraph w1["Worker 1"]
      nb["netbird-wasm SDK<br/>WireGuard peer<br/>raw TCP and UDP"]
    end
    subgraph w2["Worker 2"]
      proto["switchboard protocol module<br/>Go: HTTPS · SSH · gNMI"]
    end
  end
  relay(["NetBird relay"])
  peer["Remote NetBird peer"]
  sw["Cisco switch"]

  main -- "connect · status · ping" --> nb
  main -- "http · ssh · gnmi calls" --> proto
  proto == "dial request" ==> nb
  nb == "socket, as a MessagePort" ==> proto
  nb -- "WireGuard over WebSocket" --> relay
  relay --> peer
  peer --> sw
Loading

When the protocol module needs a socket, it calls switchboardDial(). Worker 1 dials the socket, bridges it, and sends back one end of a MessagePort. Worker 2 then treats that port as an ordinary network connection.

sequenceDiagram
  autonumber
  participant P as Page
  participant PW as Worker 2 · protocol
  participant NW as Worker 1 · netbird
  participant SW as Switch

  P->>PW: http.get(url)
  PW->>NW: switchboardDial(host, 443)
  NW->>NW: dialTcp, then connectionToPort
  NW-->>PW: MessagePort
  Note over PW,SW: The TLS handshake and the HTTP<br/>request travel on this socket.
  PW->>SW: GET /restconf/data/...
  SW-->>PW: 200, and the JSON body
  PW-->>P: status, headers, body
Loading

About

Manage remote Cisco switches via NetBird

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages