From d84c4f07134645dcc564ecaa57563d8c10f780ba Mon Sep 17 00:00:00 2001 From: Jamil Date: Wed, 3 Jul 2024 19:50:54 -0700 Subject: [PATCH] refactor: minor tweak to sans-io intro to be more conservative (#5709) Signed-off-by: Thomas Eizinger Co-authored-by: Thomas Eizinger --- website/src/app/blog/sans-io/readme.mdx | 24 +++++++++++-------- .../app/kb/architecture/tech-stack/readme.mdx | 6 +++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/website/src/app/blog/sans-io/readme.mdx b/website/src/app/blog/sans-io/readme.mdx index 4d42cb124..98f54ebfa 100644 --- a/website/src/app/blog/sans-io/readme.mdx +++ b/website/src/app/blog/sans-io/readme.mdx @@ -1,14 +1,14 @@ import Image from "next/image"; import Alert from "@/components/DocsAlert"; -At Firezone, we build secure remote access that scales, be it from your Android -phone, MacOS computer or Linux server. At the core of each app sits a -connectivity library — aptly named +At Firezone, we use Rust[^1] to build secure remote access that scales, be it +from your Android phone, MacOS computer or Linux server. At the core of each app +sits a connectivity library — aptly named [`connlib`](https://www.github.com/firezone/firezone/tree/main/rust/connlib) — that manages network connections and WireGuard tunnels to secure your traffic. After several iterations, we’ve landed on a design that we are -extremely happy with. It gives us blazingly fast and exhaustive tests, deep -customisation and overall high assurance that it does what we want it to do. +extremely happy with. It gives us fast and exhaustive tests, deep customisation +and overall high assurance that it does what we want it to do. `connlib` is built in Rust and the design we are talking about is known as sans-IO. Rust's premise of speed and memory-safety makes it a great choice for @@ -453,7 +453,7 @@ event loop are: `handle_timeout`, `handle_input`, `poll_transmit` and protocols can be implemented with these or some variation of them. As a result, it is very easy to compose these state machines together: want to query 5 STUN servers for your public IP? No problem. Just make 5 `StunBinding`s and call them -in order[^3]. +in order[^4]. In the case of Firezone, you can see this in the example of [`snownet`](https://github.com/firezone/firezone/tree/main/rust/connlib/snownet), @@ -461,7 +461,7 @@ a library that combines ICE and WireGuard and thereby exposes "magic" IP tunnels that work in any network setup to the rest of the application. `snownet` builds on top of `str0m`, a sans-IO WebRTC library and `boringtun`, an -(almost[^2]) sans-IO WireGuard implementation. We don’t need the majority of the +(almost[^3]) sans-IO WireGuard implementation. We don’t need the majority of the WebRTC stack though. The only thing we are interested in is the `IceAgent` which implements [RFC 8445](https://datatracker.ietf.org/doc/html/rfc8445). ICE uses a clever algorithm that ensures two agents, deployed into arbitrary network @@ -572,7 +572,7 @@ is sound. In comparison, `async` Rust and `&mut` almost feel somewhat at odds with each other. In Rust, `async` functions are just syntax sugar for a data structure that -implements `Future`. Spawning a `Future` into a runtime[^1] like `tokio` +implements `Future`. Spawning a `Future` into a runtime[^2] like `tokio` requires this data structure to be `'static` and therefore, it cannot contain any references, including `&mut`. To mutate state that isn't local to the `Future`, you basically have two options: @@ -644,12 +644,16 @@ Many thanks to [@algesten](https://github.com/algesten) for providing feedback on drafts of this post. [^1]: - Technically, a thread-per-core runtime could allow non-`'static` `Future`s. + For more details on Firezone's tech stack, see + [this article](/kb/architecture/tech-stack) in our architecture docs. [^2]: + Technically, a thread-per-core runtime could allow non-`'static` `Future`s. + +[^3]: `boringtun` does call `Instant::now` internally and is thus unfortunately partly impure, see https://github.com/cloudflare/boringtun/issues/391. -[^3]: +[^4]: Be sure to implement proper multiplexing of STUN messages at this point. Hint: Use the `TransactionId` and/or the server's address. diff --git a/website/src/app/kb/architecture/tech-stack/readme.mdx b/website/src/app/kb/architecture/tech-stack/readme.mdx index 8aba0c347..0fce2594f 100644 --- a/website/src/app/kb/architecture/tech-stack/readme.mdx +++ b/website/src/app/kb/architecture/tech-stack/readme.mdx @@ -57,6 +57,12 @@ These manage the control path and hot paths of the Client, respectively. They interact through a thin software layer to exchange WireGuard keys and STUN information between the control plane API and the TUN interface. + + For a deep dive into Firezone's data plane architecture and its sans-IO + design, we recommend reading [sans-IO: The secret to effective Rust for + network services](/blog/sans-io). + + Here's a high-level diagram of the various software components used in the Client applications: