a70e68c7bd
* Smolmix documentation * Add smolmix docs: landing page, tutorials, and developer page links * Add Exit Gateway services page (NR vs IPR) and link from existing docs * Update auto-generated command and API outputs * Reorg of tutorials and architecture pages * License information + remove TODO from docs.rs visibile comment + reorg readme * Add versions file for doc-wide versioning * Relative -> absolute links * Relative -> absolute links * Update license + add old tutorial code as examples * Streamline smolmix docs * Clippy * Clean up doc comments * Last pass * Add larger file download to list * set new versions * Clippy * Remove blake pin from docs + add version range to root Cargo.toml * Format example logging * Remove crate blocked component * Loose whitespace * Add doc verification script for inline mdx * Formatting * Components regen * Reorg + tighten text * Voicing cohesion pass + remove bloated examples * Voicing cont. * Reduce max download size * Small suggested clarifications * Max/docs voicing consistency (#6769) * Reduce max download size * voicing consistency across docs * New landing order w smolmix * Tweaks * Final tweaks
67 lines
3.5 KiB
Markdown
67 lines
3.5 KiB
Markdown
# smolmix
|
|
|
|
TCP/UDP tunnel over the Nym mixnet. Uses a userspace network stack (smoltcp)
|
|
to provide real `TcpStream` and `UdpSocket` types that work with the async
|
|
Rust ecosystem: tokio-rustls, hyper, tokio-tungstenite, libp2p, and anything
|
|
else built on `AsyncRead + AsyncWrite`.
|
|
|
|
## Why IP, not messages
|
|
|
|
The Nym SDK works at the message layer: you send and receive `Vec<u8>`
|
|
payloads through the mixnet. Every protocol has to be hand-adapted, with
|
|
custom framing, ordering, connection state, and flow control.
|
|
|
|
`smolmix` operates at the IP layer. A userspace smoltcp stack manages real
|
|
TCP state machines (retransmits, windowing, port allocation) and UDP
|
|
datagram delivery, and the mixnet becomes the transport underneath. Any
|
|
protocol that works over TCP or UDP works over smolmix without adaptation.
|
|
|
|
```text
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
│ Application protocols that "just work" over smolmix │
|
|
│ │
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ ┌────────────────┐ │
|
|
│ │ TLS │ │ HTTP/1.1 │ │ WebSocket │ │ libp2p │ │
|
|
│ │ (rustls) │ │ (hyper) │ │ (tungstenite)│ │ (noise+yamux) │ │
|
|
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ └───────┬────────┘ │
|
|
│ │ │ │ │ │
|
|
│ └─────────────┴──────────────┴─────────────────┘ │
|
|
│ │ │
|
|
│ tokio_smoltcp::TcpStream │
|
|
│ (AsyncRead + AsyncWrite, Send, Unpin) │
|
|
├──────────────────────────────────────────────────────────────────┤
|
|
│ smolmix Tunnel │
|
|
│ (smoltcp → mixnet → IPR) │
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Quick start
|
|
|
|
```rust
|
|
use smolmix::Tunnel;
|
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|
|
|
let tunnel = Tunnel::new().await?;
|
|
|
|
// Raw TCP, works with any protocol
|
|
let mut tcp = tunnel.tcp_connect("1.1.1.1:80".parse()?).await?;
|
|
tcp.write_all(b"GET / HTTP/1.1\r\nHost: 1.1.1.1\r\nConnection: close\r\n\r\n").await?;
|
|
|
|
// Raw UDP, datagrams over the mixnet
|
|
let udp = tunnel.udp_socket().await?;
|
|
udp.send_to(&packet, "1.1.1.1:53".parse()?).await?;
|
|
```
|
|
|
|
## Examples
|
|
|
|
```sh
|
|
cargo run -p smolmix --example tcp # HTTPS via hyper
|
|
cargo run -p smolmix --example udp # DNS via hickory-proto
|
|
cargo run -p smolmix --example websocket # WebSocket via tungstenite
|
|
```
|
|
|
|
## Architecture
|
|
|
|
See [`core/src/ARCHITECTURE.md`](core/src/ARCHITECTURE.md) for the internal
|
|
stack (smoltcp, device adapter, bridge, mixnet client).
|