Case 01 / 17 · WireGuard switch for Windows · 2026

WgSwitch

A lightweight switch for a personal WireGuard VPN: one button turns the tunnel on, and the app tells the truth about whether the server answers — not “the service is running” but a ping inside the tunnel. Several servers at once, a tray icon coloured by state, notifications and auto-reconnect, a wizard that creates keys and the config itself, and an encrypted backup of the keys. No third-party libraries; the lite build is 0.6 MB.

https://github.com/lolkekxa/WgSwitch

  • Development time: 2 days
  • Lines of code: 4,000+
  • Tests: 42
  • Lite build: 0.6 MB

Challenge

The official WireGuard client for Windows shows “Active” even when the server has long been down; turning on a second server turns off the first by default; a new tunnel means generating keys and assembling a config by hand. And once SSH and server panels are locked behind the VPN, lost keys mean a trip to the host’s web console.

Solution

WPF on .NET 8 without a single NuGet package: the window, tray and animations in the studio style; tunnels are driven by the official wireguard.exe, Windows services are queried directly through the Win32 API, and status is a ping inside the tunnel plus the handshake from wg.exe. Polling is adaptive: in the tray with tunnels off it runs every 15 seconds and starts no processes. Keys come from wg.exe, configs live in a folder only administrators can open, and the backup is encrypted with AES-256-GCM using a PBKDF2 key derived from the password. 42 tests and a GitHub Actions build: a dark-themed Inno Setup installer, portable and lite builds, checksums in the release. The app ships with a server guide: firewall, SSH and panels reachable only through the tunnel, Docker bypassing ufw.

Highlights

0 NuGet packages, lite is 0.6 MB · A ping inside the tunnel, not “service running” · Several servers at once · Keys in an encrypted .wgsb

What was built

  • One button: a thin ring and an icon in the state colour — off, connecting, connected, no response
  • An honest status: a ping to the server inside the tunnel, handshake and traffic from wg.exe
  • Several servers: chips above the button, each with its own subnet, can be on at the same time
  • A tray icon coloured by state with a per-server menu; the window opens by the clock and hides to the tray
  • Notifications when the connection drops and when it comes back, auto-reconnect after 2 minutes of silence
  • A first-run wizard: keys via wg.exe, the config in a locked folder, a ready [Peer] block for the server
  • Rename, delete, “all internet through VPN” mode and auto-connect — per server
  • An encrypted backup of servers and keys: AES-256-GCM and PBKDF2, restored right from the wizard on a new computer
  • Autostart through Task Scheduler with highest privileges — no UAC prompt at sign-in
  • Adaptive polling: every 15 seconds when idle with no processes started, memory returned to the system when the window closes
  • A dark-themed installer that installs the official WireGuard on request; portable and lite builds alongside
  • 42 tests and a GitHub Actions build: a release from a tag with notes from CHANGELOG and SHA-256
  • A server guide: firewall, SSH and panels only through the tunnel, Docker bypassing ufw, troubleshooting

Stages

  1. Switch (half a day) — The studio-style window, the tunnel service via wireguard.exe, status from SCM and ping, a tray coloured by state
  2. Servers and wizard (half a day) — Keys via wg.exe, the config in a locked folder, several servers with different subnets
  3. Reliability (half a day) — A password-protected backup, notifications, auto-reconnect, “all internet” mode
  4. Delivery (half a day) — Tests, the dark installer, GitHub Actions releases, the server guide and troubleshooting

Next project: Northstar