New WireGuardNT shatters throughput ceilings on Windows

By | August 2, 2021
Forget bendable mobile phones—we're holding out for working mobile phone plushies.
Enlarge / Forget bendable mobile phones—we’re holding out for working mobile phone plushies.

The WireGuard VPN project announced a major milestone for its Windows users today—an all-new, kernel-mode implementation of the VPN protocol called WireGuardNT. The new implementation allows for massively improved throughput on 10Gbps LAN connections—and on many WI-Fi connections, as well.

WireGuard (on Windows) and Wintun

The original implementation of WireGuard on Windows uses wireguard-go—a userspace implementation of WireGuard written in Google’s Go programming language. Wireguard-go is then tied to a virtual network device, the majority of which also lives in userspace. Donenfeld didn’t like tap-windows, the virtual network interface provided by the OpenVPN project—so he implemented his own replacement from scratch, called Wintun.

Wintun is a definite improvement over tap-windows—the OpenVPN project itself has implemented Wintun support, with impressive results (414Mbps over tap-windows vs 737Mbps over Wintun). But while using Wintun is an improvement over tap-windows, it doesn’t change the need for constant context switches from kernel space (where the “real” network stack lives) and userspace (where OpenVPN and wireguard-go both live).

In order to get rid of the remaining performance bottlenecks, the entire stack—virtual adapter, crypto, and all—need to get pulled into the kernel. On Linux, that means being a DLKM (Dynamically-Loadable Kernel Module). On Windows, that means being a proper in-kernel device driver.

WireGuardNT and the NT kernel

Ditching userspace components of the WireGuard stack on Windows, and keeping everything in-kernel means changing WireGuard to work on Windows the way it works on Linux already. In fact, WireGuardNT began as a direct port of the Linux in-kernel WireGuard implementation.

According to WireGuard creator Jason Donenfeld, once the initial port succeeded “the NT codebase quickly diverged to fit well with native NTisms and NDIS APIs. The end result is a deeply integrated and highly performant implementation of WireGuard for the NT kernel, that makes use of the full gamut of NT kernel and NDIS capabilities.”

This also, of course, means getting rid of an awful lot of context switching. The end results are solid: more than three times the top-end performance, as measured with Ethr on a pair of Equinix Metal (formerly c3.small instances.

The benefits of less context switching extend further than Xeon servers with 10Gbps interfaces, though—Donenfeld mentioned that some early testers reported that WireGuardNT solved sometimes-massive performance hits seen when using their VPN connection over Wi-Fi.

We tested the difference directly, using an HP EliteBook with an Intel AX201 Wi-Fi 6 card, connected to the router node of a test kit of Plume Wi-Fi 6 Superpods. Although our results weren’t as dramatic as those from some early testers, they do confirm a significant performance increase. On the same equipment and with the same configs, we measured WireGuardNT iperf3 running 10 percent to 25 percent faster than wireguard-go and Wintun had.

Testing WireGuardNT today

WireGuardNT is available for testing in the general Windows download for WireGuard now, as of version 0.4. But since it’s still classified as experimental, you’ll need to manually add a registry key and a DWORD to use it. Open up regedit as an administrator, then browse to HKLM–>Software. Next, create a key named WireGuard, and within that key, a DWORD named ExperimentalKernelDriver.

With ExperimentalKernelDriver set to 1, your tunnels will use the new WireGuardNT code—without it (or with it set to 0), they’ll use the default behavior, which is the old wireguard-go/wintun code. To make your change take effect, you’ll need to right-click the WireGuard icon in the system tray and click “exit.” When you open the WireGuard app again, it will honor your ExperimentalKernelDriver setting.

In the future, WireGuardNT will be enabled by default, and you’ll instead need to set a registry flag if you want the old code. Beyond that, the project plans to eventually sunset wireguard-go/wintun in the general binary entirely. The projects themselves, on the other hand, will remain, since they have wide utility beyond the stock WireGuard client.