HeadlinesBriefing HeadlinesBriefing.com

Introducing sanstun: A sans-IO, parallel-friendly WireGuard implementation in Rust

Hacker News •
×

Today, we are announcing sanstun: a sans-IO Rust implementation of the Wire Guard state machine, optimized for ease of use, security and performance through a parallel-friendly and idiomatic API. sans-IO is the idea that you design your system such that IO and side-effects are cleanly separated from the state and business logic. The IO in sans-IO doesn't just mean file or network IO; it also includes things like time and randomness. Due to their lack of side-effects, sans-IO components compose very well and are relatively easy to test. The design also avoids problems like function coloring and plays well with Rust's ownership rules.

When we first built Firezone, we reached for boringtun as our Wire Guard implementation. boringtun more or less did what we wanted, but over time, we found ourselves patching our fork over and over with bug fixes as well as API additions. The goal was to allow these patches to still be upstreamed, so we always kept the existing API working the way it was. What we found was that retaining 100% API compatibility with upstream was increasingly difficult as our product requirements evolved. After more than 2 years of using and patching boringtun, we had a pretty good idea of what the overall API of a userspace Wire Guard implementation should be. Now it exists as sanstun. A better sans-IO API

The core building blocks of the sans-IO API are: Handling inbound packets: Tunnel::handle_handshake_initiation, Tunnel::handle_handshake_response, Tunnel::handle_cookie_reply, Tunnel::begin_decapsulate & Tunnel::commit_decapsulate. Handling outbound packets: Tunnel::begin_encapsulate. Handling timer updates: Tunnel::handle_timeout & Tunnel::poll_timeout. Handling events: Tunnel::poll_event. Without internal buffering, there is no API contract that requires you to call certain APIs in a loop, which fits much better into the overall sans-IO model. To send a packet, you call Tunnel::begin_encapsulate. It is up to you to buffer the packet if you don't have a session yet. Creating a new session means sending a handshake. You can initiate a new handshake at any point with Tunnel::initiate_handshake.

Source: Hacker News · Summarized by HeadlinesBriefing