Building wgxdp
Some weeks ago I published wgxdp: an overlay network management tool for WireGuard, built in Go, with per-peer firewall rules enforced in the kernel via eBPF/XDP.
I started this side project some years ago, as I wanted to gain more experience with eBPF. Before that, I had contributed the WireGuard implementation to Flannel, and I was curious to find a way to connect the learning about eBPF to my attempts to gain more experience with Go as well. Having configured a WireGuard VPN on a VPS for years, I was always annoyed at having to handle firewall rules by myself on every host.
So when I started reading about the possibilities of eBPF/XDP, I soon realized I wanted to build a tool to manage WireGuard overlay networks and policies in one place.
How it works
The server uses wgctrl-go to configure the WireGuard interface in the kernel directly. On top of that, the server attaches an XDP program to the WireGuard interface that enforces network policies between peers. The rules live in an eBPF map and can be changed via REST API. For persistence, public keys, IP addresses and network policies are stored in a SQLite database.
The wgxdp CLI lets you create a new peer via the OAuth2 device authorization
flow, which means the client has to authenticate with your SSO provider before a
peer is created. The CLI generates a keypair with wgctrl-go. After successful device approval,
the server assigns an IP and the CLI writes out the WireGuard config. Recently
I added QR code rendering to make smartphone onboarding more convenient.
The server also serves a Progressive Web App for managing the overlay network. You get an overview of your network state (e.g. all peers and their status), and in the detail view of a peer you can manage network policies and delete the peer. There is currently no way to onboard new peers through the PWA, but that feature is coming soon.
Conclusion
Building wgxdp so far has been a great learning experience. Besides solving a real-world problem with eBPF/XDP and gaining more experience with Go, I also refreshed my knowledge of Service Workers and got back into Web Components. There are still some features missing that keep me from using it beyond a test setup: without IPv6 support and a way to configure traffic forwarding through wgxdp, I can’t run it as my real VPN. Those are the next steps for the project. For now, I’m happy with what I’ve achieved.
The code is at github.com/andreek/wgxdp.
Reading list
Two books shaped a lot of how this turned out:
- Linux Observability with BPF, David Calavera and Lorenzo Fontana
- 100 Go Mistakes and How to Avoid Them, Teiva Harsanyi
“WireGuard” is a registered trademark of Jason A. Donenfeld.