# BoringTun: Cloudflare's userspace WireGuard implementation in Rust

> BoringTun splits into a Rust library that implements the WireGuard protocol without a network stack and a Linux/macOS CLI that turns it into a working tunnel. It is a good fit for client apps and for hosts where the kernel module is not an option, and a poor fit for anyone who wants a drop-in wg-quick replacement on every platform.

**cloudflare/boringtun** — Userspace WireGuard® Implementation in Rust

- Repository: https://github.com/cloudflare/boringtun
- Stars: 7,203 · Forks: 532
- Language: Rust
- License: BSD-3-Clause
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/cloudflare-boringtun

## The problem BoringTun solves, and who has that problem

WireGuard normally lives in the kernel. On Linux that is a module, and on mobile operating systems there is no such module to load. BoringTun exists to cover both gaps: it implements the WireGuard protocol in Rust so that it can run as an ordinary process on Linux and macOS, and so that it can be compiled into iOS and Android applications as a library rather than a daemon.

The README describes the split plainly. There is an executable, boringtun-cli, which it calls a userspace WireGuard implementation for Linux and macOS, and there is the boringtun library, which the README says implements the underlying WireGuard protocol "without the network or tunnel stacks, those can be implemented in a platform idiomatic way." That second sentence is the important one. The library does the cryptography, handshake and packet framing, and leaves socket handling, routing and the tun device to the host application. This is why the supported platform table lists the library for aarch64-apple-ios, armv7-apple-ios, armv7s-apple-ios, aarch64-linux-android and arm-linux-androideabi, while the binary column is empty for all of them.

The audience follows from that. If you are writing a VPN client for a phone, or embedding WireGuard into an application that already has its own networking layer, the library is the piece you want. If you are running a server or a desktop and you want a tunnel without touching the kernel module, the CLI is the piece you want.

## How the library and the CLI divide the work

The workspace has two members, boringtun and boringtun-cli, declared in the root Cargo.toml. That layout mirrors the README's description: the library crate holds the protocol, the CLI crate holds the process that owns a tun interface and moves packets between it and the network.

The release profile in the root manifest sets lto = true and codegen-units = 1, with the same settings repeated for the bench profile. Those are build-time choices, not runtime behaviour, but they tell you the maintainers optimise the shipped binary rather than the build time. Expect slow release builds as a consequence.

For embedding, the repository exposes two binding surfaces. The README points to wireguard_ffi.h for the C ABI, which it says can be used from C and C++, from Swift through a bridging header, or from C# using DLLImport with CallingConvention set to Cdecl. Java consumers get a separate set of bindings in src/jni.rs. So the practical integration path on iOS is the C header, and on Android it is the JNI surface, not the Rust API directly.

## Installing boringtun-cli and bringing up a first tunnel

The README gives one installation route: crates.io through cargo. That installs the CLI binary.

```bash
cargo install boringtun-cli
```

If you would rather build from a checkout, the README documents separate commands for the library and the executable. The executable build is:

```bash
cargo build --bin boringtun-cli --release
```

By default the resulting binary lands in ./target/release. The README also notes you can install from a local path with cargo install --bin boringtun --path .

Starting a tunnel takes an interface name. The README shows the foreground flag and the interface name as the argument:

```bash
boringtun-cli [-f/--foreground] INTERFACE-NAME
```

Once the interface exists, you configure it with the standard wg tool, exactly as you would a kernel WireGuard tunnel. There is no BoringTun-specific configuration format to learn. The README also documents a wg-quick path through an environment variable:

```bash
sudo WG_QUICK_USERSPACE_IMPLEMENTATION=boringtun-cli WG_SUDO=1 wg-quick up CONFIGURATION
```

On Linux the README says you can avoid sudo entirely by granting the capability to the binary:

```bash
sudo setcap cap_net_admin+epi boringtun
```

On macOS the interface name has a constraint. It must match utun[0-9]+ if you name it explicitly, or you can pass utun and let the kernel pick the lowest free one. If you pass utun and set WG_TUN_NAME_FILE, the README says the kernel-chosen name is written to that file, which is how a script finds out what it actually got.

## Privilege dropping and the fwmark trap on Linux

This is the one behavioural difference the README calls out against wireguard-go on Linux, and it is easy to hit. BoringTun drops privileges after it starts. Once it has done so, it cannot set fwmark. If your configuration needs fwmark, the README gives two escapes: run with --disable-drop-privileges, or set the environment variable WG_SUDO=1. The wg-quick example above uses WG_SUDO=1 for exactly this reason.

The trade-off is real and the documentation does not soften it. You either keep the elevated privileges you started with, or you lose the ability to mark packets. wg-quick configurations commonly rely on fwmark for routing rules, so a naive attempt to run BoringTun under wg-quick without WG_SUDO=1 is likely to fail in a way that looks like a routing problem rather than a privilege problem. The README does not document rollback or cleanup behaviour for a half-configured interface, so plan for that gap yourself.

## Platform coverage is narrower than the protocol suggests

The supported platform table is the honest limit of the project, and it is worth reading column by column. The binary column has checks for x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, armv7-unknown-linux-gnueabihf and x86_64-apple-darwin. That is it. Windows appears only in the library column, as x86_64-pc-windows-msvc, and the README's own platform note says only that other platforms may be added in the future.

So BoringTun is not a way to get a userspace WireGuard tunnel on Windows, despite the library building there. If Windows is your target, the library can be embedded into something else, but there is no boringtun-cli tunnel for it in this repository. That is a hard boundary, not a configuration problem.

The second boundary is the restructuring warning at the top of the README. It states that BoringTun is undergoing a restructuring and that you should probably not rely on or link to the master branch right now, directing readers to crates.io instead. Given that the most recent releases listed are boringtun 0.5.2 and boringtun-cli 0.5.2 from 2022-07-20, the practical advice is to depend on the published crate rather than tracking the branch. The last push to the repository was on 2026-06-29, so work has continued since those releases, but the README's warning means the branch is not the stable surface.

## BoringTun against wireguard-go and the kernel module

The README itself names wireguard-go as the reference point, saying Linux behaviour should be identical to it apart from the privilege-dropping difference, and that macOS behaviour is similar. That is the most useful comparison available here, because it is the one the maintainers chose to make.

The difference is language and integration surface rather than protocol. wireguard-go is a Go implementation of the same userspace idea. BoringTun is Rust, and its distinguishing feature is the library split: the README's platform table shows the library reaching iOS and Android targets where wireguard-go is not offered as an embeddable component in the same way. If you are shipping a mobile client, that is the reason to pick BoringTun. If you are running a Linux server and just want a tunnel, the two are close enough that the README's own claim of identical behaviour means the deciding factor is probably which toolchain you already build with.

Against the kernel module the trade is clearer. A userspace implementation moves packet handling out of the kernel, which costs throughput and adds a process to supervise, in exchange for portability and for not requiring a module that matches your kernel version. The README makes no performance claim in either direction, and none should be assumed.

## Licence, maintenance and what an upgrade costs

BoringTun is licensed under the 3-Clause BSD License, and the README includes the standard contribution clause stating that intentionally submitted contributions are licensed under the same terms unless stated otherwise. BSD-3-Clause is permissive: it allows use in closed-source products, and it carries a no-endorsement clause. That clause matters if you were considering using the Cloudflare name in marketing for a product built on this library. This is a description of the licence text, not legal advice; read LICENSE.md and your own counsel's view before shipping.

On maintenance, the facts are narrow. The repository is not archived. The last push was on 2026-06-29. The most recent releases listed are boringtun 0.5.2 and boringtun-cli 0.5.2, both from 2022-07-20. There is a CHANGELOG.md at the top level, so release history is tracked in the repository rather than only on crates.io.

The upgrade cost is shaped by the README's restructuring warning. If you depend on a published crate version, your upgrade path is a version bump with whatever API changes the changelog records. If you pinned to a git revision of master, you are on the surface the README explicitly tells people not to rely on, and you should expect that the branch moves under you. The library and CLI are versioned separately, so a boringtun-cli upgrade does not automatically imply a boringtun library upgrade.

## Conclusion

Adopt BoringTun if you are building a WireGuard client on iOS or Android, or you need a userspace tunnel on Linux or macOS where the kernel module is unavailable. Do not adopt it if you need Windows as a tunnel endpoint, or if you intend to link against the master branch: the README warns against relying on master and points to crates.io instead. Before committing, verify two things for yourself: that the crate version you pull from crates.io matches the API you wrote against, and whether your deployment needs fwmark, because privilege dropping after startup blocks it unless you pass --disable-drop-privileges or set WG_SUDO=1.

## FAQ

### Is WireGuard completely free?

BoringTun itself is licensed under the 3-Clause BSD License, a permissive licence that also carries a no-endorsement clause. The README notes that WireGuard is a registered trademark of Jason A. Donenfeld and that BoringTun is not sponsored or endorsed by him.

### What are the disadvantages of WireGuard?

The README does not discuss WireGuard's disadvantages in general. It does document one BoringTun-specific drawback: the implementation drops privileges when started, and once it has done so it cannot set fwmark, so configurations that need fwmark must run with --disable-drop-privileges or WG_SUDO=1.

### Is WireGuard a good VPN?

The README makes no comparative quality claim about WireGuard as a VPN. It states only that BoringTun is an implementation of the WireGuard protocol designed for portability and speed, and that it is deployed on iOS and Android consumer devices and Cloudflare Linux servers.

### What protocol does WireGuard VPN use?

WireGuard is the protocol, and BoringTun is an implementation of it. The README describes the boringtun library as implementing the underlying WireGuard protocol without the network or tunnel stacks, which the host application supplies.

## Sources

- [cloudflare/boringtun on GitHub](https://github.com/cloudflare/boringtun)
- [Issues](https://github.com/cloudflare/boringtun/issues)
- [License: BSD-3-Clause](https://github.com/cloudflare/boringtun/blob/master/LICENSE)
- [README](https://github.com/cloudflare/boringtun/blob/master/README.md)
- [Releases](https://github.com/cloudflare/boringtun/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cloudflare-boringtun
