//! aura-tunnel — the Aura VPN data-plane tunnel (project §8). //! //! This crate turns a host's IP traffic into something the encrypted transport can carry, and back //! again. It has four pieces: //! //! * [`AuraTun`] — a cross-platform layer-3 TUN device (Linux/macOS via the `tun` crate; Windows via //! `wintun`, `cfg`-gated). See [`tun`](mod@crate::tun). //! * [`RouteTable`] / [`RouteAction`] — a longest-prefix-match split-tunnel routing table deciding //! VPN-vs-direct per destination IP. See [`routes`](mod@crate::routes). //! * [`AuraDns`] — a hickory-backed resolver that registers resolved domain addresses as host //! routes in a shared [`RouteTable`]. See [`dns`](mod@crate::dns). //! * [`AuraRouter`] — the run-loop bridging the TUN device and an //! [`aura_proto::PacketConnection`]. See [`router`](mod@crate::router). //! //! ## Wiring it together (for the CLI) //! //! The router is generic over the [`PacketIo`] device seam and shares the routing table and the //! packet connection by `Arc`: //! //! ```no_run //! # async fn demo(conn: std::sync::Arc) -> anyhow::Result<()> { //! use std::sync::Arc; //! use tokio::sync::RwLock; //! use aura_tunnel::{AuraDns, AuraRouter, AuraTun, RouteAction, RouteTable}; //! //! // 1. Build a shared routing table (default: everything through the VPN). //! let routes = Arc::new(RwLock::new(RouteTable::new(RouteAction::Vpn))); //! routes.write().await.add_cidr("192.168.0.0/16".parse()?, RouteAction::Direct); //! //! // 2. Optionally resolve domains into host routes. //! let mut dns = AuraDns::new(Arc::clone(&routes)).await?; //! dns.resolve_and_register("example.com", RouteAction::Direct).await?; //! //! // 3. Create the TUN device (needs privileges). //! let tun = AuraTun::create("aura0", "10.7.0.2".parse()?, 24, 1420).await?; //! //! // 4. Build the router from the TUN, the table, and the connection, then run it. //! let router = AuraRouter::new(tun, routes, conn); //! router.run().await?; //! # Ok(()) //! # } //! ``` #![cfg_attr(not(windows), forbid(unsafe_code))] #![warn(missing_docs)] pub mod dns; pub mod router; pub mod routes; pub mod tun; pub use dns::AuraDns; pub use router::{dst_ip, AuraRouter, PacketCounters}; pub use routes::{RouteAction, RouteTable}; pub use tun::{AuraTun, PacketIo}; use thiserror::Error; /// Errors produced by the tunnel data plane. /// /// The router and DNS surfaces mostly return [`anyhow::Result`] (they compose I/O, the `tun`/`wintun` /// backends, hickory, and the [`aura_proto::PacketConnection`] contract, all of which already carry /// rich context). This enum names the tunnel-specific failure modes for callers that want to match /// on them, and converts cleanly from the underlying I/O and resolver errors. #[derive(Debug, Error)] pub enum TunnelError { /// Creating or configuring the TUN/wintun device failed. #[error("TUN device error: {0}")] Device(String), /// An I/O error while reading from or writing to the TUN device. #[error("TUN I/O error: {0}")] Io(#[from] std::io::Error), /// The requested TUN address/prefix was not a valid network. #[error("invalid TUN address or prefix: {0}")] InvalidAddress(#[from] ipnetwork::IpNetworkError), /// DNS resolution failed. #[error("DNS resolution error: {0}")] Dns(#[from] hickory_resolver::error::ResolveError), /// The underlying encrypted packet connection failed. #[error("packet connection error: {0}")] Connection(String), }