Skip to content

Instantly share code, notes, and snippets.

@rot256

rot256/final.md Secret

Last active July 26, 2022 17:13
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rot256/e4ba56cdff7e1bffe6e7e62c4cd9b85c to your computer and use it in GitHub Desktop.
Save rot256/e4ba56cdff7e1bffe6e7e62c4cd9b85c to your computer and use it in GitHub Desktop.

Introduction

WireGuard is currently implemented as a kernel module for Linux. Although this offers advantages over a user space implementation, both in terms of speed and latency, there are obvious reasons for also desiring a user space implementation:

  1. Portability. A user space implementation is easier to port for a wide range of platforms, users of Windows, OSX and BSD in addition to older versions of Linux cannot currently use WireGuard.

  2. Permissions. The environment may not allows for the installation of a kernel module (such as OpenVZ or in Docker) In the future, WireGuard will hopefully make it into the kernel itself mitigating some of these issues, but people are likely to run old Linux kernels well into the foreseeable future.

  3. Ideology. Although the code base of the kernel module is small, some people believe that VPN clients/servers belong in user space.

My goal has been to create such a user space implementation in Golang.

Status

The code can be found at:

git.zx2c4.com/wireguard-go/tree

The current version compiles and works (with the following disclaimer) on Linux, OSX and Windows (using the OpenVPN TAP driver).

Due to the nature of WireGuard, where peoples life, privacy and liberty may depend on the correctness of the software I do not consider the software anything but experimental before the code has been thoroughly reviewed by a number of people. In addition the kernel implementation is also under heavy development and the specification still subject to change.

Linux

The implementation functions with the CAP_NET_ADMIN capability. The interface is configured using the wg tool found in the WireGuard repository (no need to build/install the kernel module itself).

OSX

The application must be run as root to create the TUN device.

The WireGuard tools compile on OSX and functions the same.

Windows

Tools (wg & wg-quick) for configuring the interface (UAPI client) are not available on this platform yet. These tools are not part of the project. Testing was done by using a python script to write transcripts of the UAPI protocol to the bidirectional pipe on the Windows system.

This version requires the OpenVPN Tap-windows driver (NDIS 6)

Speed

It was a goal to achieve performance exceeding that of OpenVPN, the implementation out performs OpenVPN by a significant margin and fully saturates a gigabit connection using commodity laptop hardware. The primary reason for the difference in performance is the use of multi-threading and the speed of the cryptographic primitives employed in WireGuard (OpenVPN does 2 passes over the content).

Deficiencies

Although the current version functions (with the previous disclaimer in mind).

The following 4 things must be fixed before the implementation is ready for use by the general public:

Better handling of key material

Due to the API in golang.org/x/crypto/* and the nature of Go, handling cryptographic secrets in a satisfactory way is currently challenging.

A common practice within the /x/crypto packages is providing a "New" function which returns an instance implementing an interface (e.g cipher.AEAD or hash.Hash), with the result that cryptographic state is stored on the ordinary heap (where it may be swapped to disk).

This issue is of great importance due to WireGuards forward secrecy guarantees.

Dropping of capabilities / privileges

This also includes additional measures to contain the process (e.g separation from the file system)

Source address caching

After an incoming datagram is received and authenticated, subsequent messages send to the peer should originate from the destination address of the datagram. There is no obvious way to do this within the net package, but required for the implementation to work correctly behind NAT in some cases.

ICMP responses

According to the specification, a WireGuard implementation should respond to a number of error events with ICMP messages. These include (among others) when there is no peer configured for the given destination address (when handling an outbound packet).

Future work

I plan on working on the 4 points mentioned above with a primary focus on Linux. I hope the announcement of an experimental user space implementation will attract additional contributors, primarily on platforms for which WireGuard is not currently available (OSX, Windows and BSD).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment