The Platform
VPN Works is the VPN, rebuilt as an operating system. A VPN decides how traffic leaves a machine. VPN Works makes that decision per program, and builds it the way an OS is built: a small kernel that does the work no plugin may do, drivers for each way out, a system-call interface, and apps that add everything else without touching the kernel.
It’s an OS for network paths, and you don’t boot it. It’s one program, vpnw, that runs on Linux or macOS without root. The current release is 0.8.0, out on October 14, 2026, open source under Apache 2.0 at github.com/VPNWorks/vpnw.
Built Like an OS
| In an OS | In VPN Works | What it does |
|---|---|---|
| Processes | programs you run under vpnw | each gets a network of its own |
| Kernel | the core, vpnw |
seals, decides, carries, records |
| Drivers | paths | direct, proxy, proxy over TLS, WireGuard |
| System calls | the plugin interface | the only way a plugin reaches the kernel |
| Permissions | manifests, signatures, sandbox | what each plugin may do, and who it came from |
| Apps | plugins | features added without touching the kernel |
| Logs | the record | every decision, as an event |

The Kernel: vpnw
The kernel does four things, and keeps only what a plugin couldn’t do instead.
Seal. On Linux a program runs in a network namespace of its own, with nothing in it but loopback. The only things listening there are vpnw’s two proxy ports. A seccomp filter keeps the program off Unix sockets and io_uring, so it can’t ask a local service like Docker to connect for it. A program that ignores proxy settings has no route anywhere. It doesn’t leak around vpnw; it just fails.
Decide. A policy is a short TOML file, or a few flags: allow and deny rules for hosts, subdomains, addresses and ranges, with ports if you want them, plus deny_private for loopback, private ranges and cloud metadata. Every connection is decided in the same fixed order. A name that isn’t allowed is never even looked up, because a DNS query can carry data out too. Guard plugins get a say after the policy.
Carry. Every connection goes through vpnw’s broker, which speaks HTTP CONNECT, plain HTTP and SOCKS5, so ordinary programs work unchanged: curl, git, pip, Python, Go and Node.js 22.21 and later all honor the proxy settings vpnw sets. Plugins never carry traffic; only the kernel does.
Record. Every decision is an event: the host, the address, the port, the rule that decided it, the bytes each way. Never a payload, a URL path, a header or a password. Events print as text, save as JSON Lines, and feed the plugins.
Drivers: Paths
A path is how allowed connections leave the machine. Each one is a driver in the kernel, because each one carries traffic.
| Path | What it is |
|---|---|
| Direct | from this machine, as the program would have connected anyway |
| SOCKS5 or HTTP proxy | through a proxy you run or rent |
| Proxy over TLS | the same, with the proxy’s certificate checked and a token sent |
| A list of exits | proxies over TLS used in order; when one stops answering, the next takes over |
| WireGuard | a WireGuard tunnel that vpnw runs itself, from the wg-quick file your VPN provider or wg hands out |
The WireGuard driver runs in user space, inside vpnw, with wireguard-go for the protocol and gVisor’s TCP/IP stack. Nothing gets set up on the machine: no root, no kernel module, no network interface. One program goes through the tunnel and everything else carries on as before. Names are looked up through the tunnel too, and a lying answer can’t send a program to loopback or cloud metadata through it. Every release of the driver must pass Lab, a kit of faults: a silent peer, lost handshakes, an impostor peer, a DNS server that lies. WireGuard paths in detail
The driver can also take its configs from a Tunnel plugin, which says when to move to the next one. The driver still runs every tunnel: it brings the next one up before anything moves, lets open connections finish on the old one, and never sends traffic around them. Tunnel plugins
The far end of a proxy path can be VPN Works too. vpnw exit runs the same kernel on a server with fixed addresses: it takes each client’s requests over TLS with a token, decides every one again with that client’s own policy, and connects from the client’s own address. Plugins run there as well. Exit
System Calls: The Plugin Interface
Plugins are WebAssembly modules that vpnw runs in a sandbox inside its own process. A plugin gets no files, no network, no environment and no arguments. It reaches the kernel only through host calls, and only the ones its manifest asks for. vpnw refuses a module that imports anything else before running a single instruction of it.
The rules are the same for every plugin, the built-in ones included:
- Time budgets. A plugin that crashes or runs past its budget is stopped, and the run carries on.
- Fail closed. A Guard that fails refuses every connection after it.
- No slowdowns. An Observer that falls behind loses events, counted and reported, and nothing waits for it.
- Signed. Plugins are signed with Ed25519, and vpnw installs them only from keys you trust, unless you say otherwise.
- Asked for. Writing to the console, adding events to the record, appending to a file of its own and reading one folder are permissions a plugin’s manifest must ask for. The file is one vpnw creates new; the plugin can’t read it or reach any other. The folder is one vpnw opens for it, and nothing outside it can be read.
Apps: Plugins
| Type | What it does | Status |
|---|---|---|
| Observer | watches a run’s events as they happen | open; built in: Trace, the console, and Ledger, which seals the record |
| Advisor | reads recorded traces, or files of its own, and writes advice | open; built in: Learn, which drafts a policy, and ledger-verify, which checks a sealed record |
| Guard | can refuse a connection the policy allowed | open |
| Tunnel | hands WireGuard configs to the kernel and says when to move to the next | open; built in: rotate, which rotates through a folder of configs |
| Exit, Identity | plugin types not defined yet; vpnw exit itself is part of the kernel |
reserved |
The console you read every day is a plugin, Trace, through the same interface as anyone else’s. First-party plugins get no back door. All plugins, and how to write one
Processes: What Runs on It
Today, one program at a time: you name a program, and vpnw runs it with its own seal, policy, path and record. AI agents, scrapers, build jobs and CI steps are the programs it was built for, because they act on their own and follow instructions they find in text.
Next comes gateway mode: one policy for every device behind a machine. That’s when VPN Works starts doing a router’s job too. It’s on the roadmap.
What VPN Works Isn’t
- A VPN service. It runs no servers for you and sells no exits. It uses the ones you have: your VPN provider’s, your office’s, a WireGuard server of your own, or
vpnw exiton a server you run. - An OS you boot. It’s one program on top of Linux or macOS. The OS is in how it’s built.
- A router, yet. It covers the programs you run under it. Gateway mode comes later.
- A new tunnel protocol. It speaks WireGuard, through the official Go implementation.
Measured
By the script that records every number on this site: the sandbox on a GitHub Actions Linux runner, the rest on one Linux machine with 2 CPUs. That machine’s speed varies from day to day, so compare times and speeds within one release’s figures; measured side by side on the same evening, 0.7.0 and 0.8.0 moved data through a WireGuard tunnel at about the same speed.
| Ways out of the sealed sandbox tried | 17, all blocked, IPv6 included |
| Test functions | 236 of 236 passed, end-to-end runs of the real binary included |
| Faults thrown by Lab at WireGuard tunnels, run directly and through the rotate plugin | 36, all handled |
| Tunnel plugin checks, with the real binary and real WireGuard peers | 9 of 9 passed |
| Exit checks, with the real binaries | 21 of 21 passed |
| Requests decided the same way by a run and by an exit | 513 of 513 |
| Statements covered | 85.4% |
| Fuzz targets | 17, all clean |
| A connection opened through a WireGuard tunnel | 0.41 ms |
| Data through a WireGuard tunnel, both ends on that machine | 54 MB/s |
| Moving to the next config’s tunnel, handshake included | 31.5 ms |
| A connection opened through an exit, TLS and token included | 1.8 ms |
| Data through an exit, both ends on that machine | 541 MB/s |
| A Guard plugin’s decision | 0.17 ms |
| One event sealed by the Ledger plugin | 0.17 ms |
| Kinds of edit to a sealed record | 22: 21 reported as changes, 1 as a run cut short |
| One event through the Trace plugin | 0.46 ms |
| The rotate plugin asked for the next config, from a folder of 20 | 1.7 ms |
The full output is in test/results. How it was tested · What 0.4.1 added · Lab · Exit · Tunnel plugins
What It Doesn’t Do Yet
Sealed runs need Linux. On macOS, programs that honor proxy settings run through any path, WireGuard included, but nothing stops one that ignores them.
TCP only, on every path. UDP and QUIC are refused.
Network only. A sealed program can read whatever your user can read. It can only send it where the policy allows.