Using onetun as a Library

While onetun is primarily a CLI tool, its core logic is exposed as a library, allowing you to embed a user-space WireGuard tunnel into your own Rust applications.

Dependencies

Add onetun to your Cargo.toml. You likely want to disable the default features (which include the CLI binary dependencies).

[dependencies]
onetun = { version = "0.3.10", default-features = false }
tokio = { version = "1", features = ["full"] }
anyhow = "1"

Basic API

The entry point is onetun::start_tunnels, which takes a configuration and an event bus.

use std::net::SocketAddr;
use std::sync::Arc;
use onetun::config::{Config, PortForwardConfig, PortProtocol, StaticSecret, PublicKey};
use onetun::events::Bus;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. Initialize the Event Bus
    let bus = Bus::default();

    // 2. Define Configuration
    let config = Config {
        // Define port forwards (Local -> Remote)
        port_forwards: vec![
            PortForwardConfig {
                source: "127.0.0.1:8080".parse()?,
                destination: "192.168.4.2:80".parse()?,
                protocol: PortProtocol::Tcp,
                remote: false,
            }
        ],
        remote_port_forwards: vec![], // For reverse tunneling (if supported)

        // Keys (Keep these secret in real apps)
        private_key: Arc::new(StaticSecret::from([0u8; 32])), 
        endpoint_public_key: Arc::new(PublicKey::from([0u8; 32])),
        preshared_key: None,

        // Connection Details
        endpoint_addr: "140.30.3.182:51820".parse()?,
        endpoint_bind_addr: "0.0.0.0:0".parse()?,
        source_peer_ip: "192.168.4.3".parse()?,
        keepalive_seconds: Some(25),
        max_transmission_unit: 1420,

        // Misc
        log: "info".to_string(),
        warnings: vec![],
        pcap_file: None,
    };

    // 3. Start the tunnels
    // This spawns tasks onto the Tokio runtime and returns immediately.
    onetun::start_tunnels(config, bus).await?;

    // 4. Keep the main thread alive
    futures::future::pending().await
}