diff --git a/mixtcp/README.md b/mixtcp/README.md deleted file mode 100644 index 96cffa8d9c..0000000000 --- a/mixtcp/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# MixTCP - -**TODO change name to smolmix** - -This is an initial proof of concept of a SmolTCP `device` that uses the Mixnet for transport. It relies on the `IpMixStream` module from the Rust SDK to set up a connection with an Exit Gateway's Ip-Packet-Router, meaning that this is the IP that is seen by the receiver of the request. - -This can be used as the basis for building more generic transport crates on top of the Mixnet (e.g. trying to mirror the interface of a common HTTPS crate) whilst abstracting away the complexities of using the Mixnet for transport. - -More to come in the future. - -`examples/` contains examples for: -- `cloudflare_ping` - HTTPS request to Cloudflare through the mixnet -- `https_client` - `reqwest`-like HTTPS `GET` client with timed clearnet comparison -- `tls` - TLS handshake diagnostics with state logging -- `dns_udp` - DNS A-record lookup over UDP with timed clearnet comparison - -## Component Interaction -```sh - create_device() - | - +----------+-------+-------+-----------+ - | | | | - v v v v - NymIprDevice NymIprBridge ShutdownHandle IpPair - | | | (10.0.x.x) - | | | - +- channels + shutdown signal - | - v - IpMixStream - | - v - Mixnet -``` diff --git a/sdk/rust/nym-sdk/README.md b/sdk/rust/nym-sdk/README.md index 16f1989414..1493a1742c 100644 --- a/sdk/rust/nym-sdk/README.md +++ b/sdk/rust/nym-sdk/README.md @@ -4,5 +4,6 @@ This repo contains several components: - `mixnet`: exposes Nym Client builders and methods. This is useful if you want to interact directly with the Client, or build transport abstractions. - `tcp_proxy`: exposes functionality to set up client/server instances that expose a localhost TcpSocket to read/write to like a 'normal' socket connection. `tcp_proxy/bin/` contains standalone `nym-proxy-client` and `nym-proxy-server` binaries. - `clientpool`: a configurable pool of ephemeral Nym Clients which can be created as a background process and quickly grabbed. +- `stream_wrapper`: made up of two parts: a TCP-Socket-like abstraction (`mixnet_stream_wrapper.rs`) for a Nym Client, and an abstraction built on top of this (`mixnet_stream_wrapper_ipr`) which allows for client-side integrations to send IP packets through Exit Gateways' IpPacketRouter, and use the Mixnet as a proxy. For an example of where this is used, see the `smolmix` crate. Documentation can be found [here](https://nym.com/docs/developers/rust). diff --git a/mixtcp/Cargo.toml b/smolmix/Cargo.toml similarity index 97% rename from mixtcp/Cargo.toml rename to smolmix/Cargo.toml index 30ff20b18a..34adbe52aa 100644 --- a/mixtcp/Cargo.toml +++ b/smolmix/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mixtcp" +name = "smolmix" version = "0.0.1" edition = "2021" license.workspace = true diff --git a/mixtcp/examples/cloudflare_ping.rs b/smolmix/examples/cloudflare_ping.rs similarity index 98% rename from mixtcp/examples/cloudflare_ping.rs rename to smolmix/examples/cloudflare_ping.rs index 5b1297e359..9bb2a5b2b2 100644 --- a/mixtcp/examples/cloudflare_ping.rs +++ b/smolmix/examples/cloudflare_ping.rs @@ -9,8 +9,8 @@ mod support; -use mixtcp::create_device; use nym_sdk::stream_wrapper::{IpMixStream, NetworkEnvironment}; +use smolmix::create_device; use smoltcp::{ iface::{Config, Interface, SocketSet}, socket::tcp, @@ -119,7 +119,7 @@ async fn main() -> Result<(), BoxError> { // Send simple HTTP request request_start = tokio::time::Instant::now(); - let request = b"GET /cdn-cgi/trace HTTP/1.1\r\nHost: cloudflare.com\r\nUser-Agent: mixtcp-test/1.0\r\nAccept: */*\r\nConnection: close\r\n\r\n"; + let request = b"GET /cdn-cgi/trace HTTP/1.1\r\nHost: cloudflare.com\r\nUser-Agent: smolmix-test/1.0\r\nAccept: */*\r\nConnection: close\r\n\r\n"; match tls_conn.send(request, socket) { Ok(_) => { info!("HTTPS request sent"); diff --git a/mixtcp/examples/dns_udp.rs b/smolmix/examples/dns_udp.rs similarity index 99% rename from mixtcp/examples/dns_udp.rs rename to smolmix/examples/dns_udp.rs index 472200c18b..598ee25783 100644 --- a/mixtcp/examples/dns_udp.rs +++ b/smolmix/examples/dns_udp.rs @@ -15,8 +15,8 @@ use std::time::Duration; use hickory_proto::op::{Message, MessageType, OpCode, Query}; use hickory_proto::rr::{Name, RData, RecordType}; use hickory_resolver::TokioResolver; -use mixtcp::create_device; use nym_sdk::stream_wrapper::{IpMixStream, NetworkEnvironment}; +use smolmix::create_device; use smoltcp::{ iface::{Config, Interface, SocketSet}, socket::udp, diff --git a/mixtcp/examples/https_client.rs b/smolmix/examples/https_client.rs similarity index 95% rename from mixtcp/examples/https_client.rs rename to smolmix/examples/https_client.rs index 3d9e9c0803..fd9d7c897a 100644 --- a/mixtcp/examples/https_client.rs +++ b/smolmix/examples/https_client.rs @@ -9,9 +9,9 @@ mod support; -use mixtcp::{create_device, NymIprDevice}; use nym_sdk::stream_wrapper::{IpMixStream, NetworkEnvironment}; use reqwest::StatusCode; +use smolmix::{create_device, NymIprDevice}; use smoltcp::{ iface::{Config, Interface, SocketSet}, socket::tcp, @@ -25,14 +25,14 @@ use support::{BoxError, TlsOverTcp}; use tracing::info; /// Reqwest-ish client right now, just a handrolled GET request for the example -pub struct MixtcpReqwestClient { +pub struct SmolmixReqwestClient { device: Arc>, bridge_handle: tokio::task::JoinHandle<()>, - shutdown_handle: Option, + shutdown_handle: Option, _allocated_ip: Ipv4Address, } -impl MixtcpReqwestClient { +impl SmolmixReqwestClient { pub async fn new() -> Result { let ipr_stream = IpMixStream::new(NetworkEnvironment::Mainnet).await?; let (mut device, bridge, shutdown_handle, allocated_ips) = @@ -74,7 +74,7 @@ impl MixtcpReqwestClient { let _ = self.bridge_handle.await; } - pub async fn get(&self, url: &str) -> Result { + pub async fn get(&self, url: &str) -> Result { let parsed_url = reqwest::Url::parse(url)?; let host = parsed_url.host_str().ok_or("URL has no host")?.to_string(); let path = parsed_url.path().to_string(); @@ -83,7 +83,7 @@ impl MixtcpReqwestClient { self.simple_get_request(&host, &path).await?; let (status, body) = Self::parse_simple_response(&response_bytes)?; - Ok(MixtcpResponse { + Ok(SmolmixResponse { status, body, handshake_duration, @@ -159,7 +159,7 @@ impl MixtcpReqwestClient { request_start = tokio::time::Instant::now(); let request = format!( - "GET {} HTTP/1.1\r\nHost: {}\r\nUser-Agent: mixtcp/1.0\r\nAccept: */*\r\nConnection: close\r\n\r\n", + "GET {} HTTP/1.1\r\nHost: {}\r\nUser-Agent: smolmix/1.0\r\nAccept: */*\r\nConnection: close\r\n\r\n", path, domain ); tls_conn.send(request.as_bytes(), socket)?; @@ -222,14 +222,14 @@ impl MixtcpReqwestClient { } } -pub struct MixtcpResponse { +pub struct SmolmixResponse { status: u16, body: String, handshake_duration: Duration, request_duration: Duration, } -impl MixtcpResponse { +impl SmolmixResponse { pub fn status(&self) -> StatusCode { StatusCode::from_u16(self.status).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR) } @@ -258,7 +258,7 @@ async fn main() -> Result<(), BoxError> { ); info!("Setting up mixnet client..."); - let client = MixtcpReqwestClient::new().await?; + let client = SmolmixReqwestClient::new().await?; let mixnet_response = client.get(test_url).await?; let mixnet_status = mixnet_response.status(); let handshake_duration = mixnet_response.handshake_duration; diff --git a/mixtcp/examples/support/mod.rs b/smolmix/examples/support/mod.rs similarity index 98% rename from mixtcp/examples/support/mod.rs rename to smolmix/examples/support/mod.rs index 45bccfd536..9dfbaeacff 100644 --- a/mixtcp/examples/support/mod.rs +++ b/smolmix/examples/support/mod.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-2.0-only -//! Shared helpers for the TCP/TLS mixtcp examples. +//! Shared helpers for the TCP/TLS smolmix examples. //! //! Provides a [`TlsOverTcp`] adapter that bridges rustls with smoltcp TCP //! sockets, plus common utilities like [`init_logging`]. diff --git a/mixtcp/examples/tls.rs b/smolmix/examples/tls.rs similarity index 99% rename from mixtcp/examples/tls.rs rename to smolmix/examples/tls.rs index ebbce5e638..ee8803a720 100644 --- a/mixtcp/examples/tls.rs +++ b/smolmix/examples/tls.rs @@ -10,8 +10,8 @@ mod support; -use mixtcp::create_device; use nym_sdk::stream_wrapper::{IpMixStream, NetworkEnvironment}; +use smolmix::create_device; use smoltcp::{ iface::{Config, Interface, SocketSet}, socket::tcp, diff --git a/mixtcp/src/bridge.rs b/smolmix/src/bridge.rs similarity index 96% rename from mixtcp/src/bridge.rs rename to smolmix/src/bridge.rs index 1c6f4740fd..8068a0baab 100644 --- a/mixtcp/src/bridge.rs +++ b/smolmix/src/bridge.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-2.0-only -use crate::error::MixtcpError; +use crate::error::SmolmixError; use nym_ip_packet_requests::codec::MultiIpPacketCodec; use nym_sdk::stream_wrapper::IpMixStream; use tokio::sync::{mpsc, oneshot}; @@ -75,7 +75,7 @@ impl NymIprBridge { /// /// The loop exits when a shutdown signal is received, channels are closed, /// or an error occurs. On exit the mixnet client is disconnected gracefully. - pub async fn run(mut self) -> Result<(), MixtcpError> { + pub async fn run(mut self) -> Result<(), SmolmixError> { info!("Starting Nym IPR bridge"); let mut packets_sent = 0; let mut packets_received = 0; @@ -115,7 +115,7 @@ impl NymIprBridge { // Forward to device via channel if self.rx_sender.send(packet.to_vec()).is_err() { error!("Failed to send packet to device - receiver dropped"); - return Err(MixtcpError::ChannelClosed); + return Err(SmolmixError::ChannelClosed); } packets_received += 1; debug!("Total packets received: {}", packets_received); diff --git a/mixtcp/src/device.rs b/smolmix/src/device.rs similarity index 100% rename from mixtcp/src/device.rs rename to smolmix/src/device.rs diff --git a/mixtcp/src/error.rs b/smolmix/src/error.rs similarity index 94% rename from mixtcp/src/error.rs rename to smolmix/src/error.rs index 0d675a79e2..226fcb9efd 100644 --- a/mixtcp/src/error.rs +++ b/smolmix/src/error.rs @@ -4,7 +4,7 @@ use thiserror::Error; #[derive(Error, Debug)] -pub enum MixtcpError { +pub enum SmolmixError { #[error("Channel closed")] ChannelClosed, diff --git a/mixtcp/src/lib.rs b/smolmix/src/lib.rs similarity index 94% rename from mixtcp/src/lib.rs rename to smolmix/src/lib.rs index 97c058caec..0575b1d4ad 100644 --- a/mixtcp/src/lib.rs +++ b/smolmix/src/lib.rs @@ -7,7 +7,7 @@ mod error; pub use bridge::{BridgeShutdownHandle, NymIprBridge}; pub use device::NymIprDevice; -pub use error::MixtcpError; +pub use error::SmolmixError; use nym_ip_packet_requests::IpPair; use nym_sdk::stream_wrapper::IpMixStream; @@ -27,7 +27,7 @@ use tokio::sync::mpsc; /// to disconnect from the mixnet cleanly. pub async fn create_device( mut ipr_stream: IpMixStream, -) -> Result<(NymIprDevice, NymIprBridge, BridgeShutdownHandle, IpPair), MixtcpError> { +) -> Result<(NymIprDevice, NymIprBridge, BridgeShutdownHandle, IpPair), SmolmixError> { // Ensure the stream is connected if !ipr_stream.is_connected() { ipr_stream.connect_tunnel().await?; @@ -37,7 +37,7 @@ pub async fn create_device( // further 'up' the flow in the code calling this fn. let allocated_ips = *ipr_stream .allocated_ips() - .ok_or(MixtcpError::NotConnected)?; + .ok_or(SmolmixError::NotConnected)?; // Create channels for device <-> bridge communication let (tx_to_bridge, tx_from_device) = mpsc::unbounded_channel();