rust-tunnel 1.0.36

A tunnel with an obfuscated datagram transport for horrible networks
Documentation
use rand_core::RngCore;
pub use {smol, smol::prelude::*};

pub async fn gen_key() -> x25519_dalek::StaticSecret {
    let mut key: [u8; 32] = [0u8; 32];
    rand_core::OsRng.fill_bytes(&mut key);
    let key: x25519_dalek::StaticSecret = x25519_dalek::StaticSecret::from(key);
    return key;
}

#[async_recursion::async_recursion]
pub async fn get_key() -> x25519_dalek::StaticSecret {
    let home: String = dirs::home_dir()
        .unwrap()
        .into_os_string()
        .into_string()
        .unwrap();
    let keyfile: String = home + "/tunnel-private.key";

    let key: x25519_dalek::StaticSecret = match std::fs::read(&keyfile) {
        Ok(v) => {
            if v.len() != 32 {
                std::fs::remove_file(&keyfile).unwrap();
                return get_key().await;
            }
            let mut k: [u8; 32] = [0u8; 32];
            for i in 0..32 {
                k[i] = v[i];
            }
            x25519_dalek::StaticSecret::from(k)
        }
        Err(_) => {
            let key: x25519_dalek::StaticSecret = gen_key().await;
            let keyfile_value: [u8; 32] = key.to_bytes();
            std::fs::write(&keyfile, keyfile_value).unwrap();
            key
        }
    };
    return key;
}

pub async fn client(
    pk: x25519_dalek::PublicKey,
    client: std::net::SocketAddr,
    server: std::net::SocketAddr,
) {
    let tunnel_stats: std::sync::Arc<sosistab::StatsGatherer> =
        std::sync::Arc::new(sosistab::StatsGatherer::new_active());
    let tunnel_client: sosistab::ClientConfig =
        sosistab::ClientConfig::new(sosistab::Protocol::DirectUdp, server, pk, tunnel_stats);

    let tunnel_conn: sosistab::Session = tunnel_client.connect().await.unwrap();
    let tunnel_conn: sosistab::Multiplex = tunnel_conn.multiplex();

    let tcp_server: smol::net::TcpListener = smol::net::TcpListener::bind(client).await.unwrap();
    let mut tcp_in = tcp_server.incoming();

    loop {
        let tcp_conn: smol::net::TcpStream = tcp_in.next().await.unwrap().unwrap();
        let tunnel_conn: sosistab::RelConn = tunnel_conn.open_conn(None).await.unwrap();

        smol::spawn(
            smol::io::copy(tunnel_conn.clone(), tcp_conn.clone())
                .race(smol::io::copy(tcp_conn, tunnel_conn)),
        )
        .detach();
    }
}

pub async fn server(
    sk: x25519_dalek::StaticSecret,
    server: std::net::SocketAddr,
    tunnel_to: std::net::SocketAddr,
) {
    let tunnel_server: sosistab::Listener = sosistab::Listener::listen_udp(
        server,
        sk,
        |_size: usize, _peer: std::net::SocketAddr| { /* on receive */ },
        |_size: usize, _peer: std::net::SocketAddr| { /* on send */ },
    )
    .await
    .unwrap();

    loop {
        let tunnel_conn: sosistab::Session = tunnel_server.accept_session().await.unwrap();
        let tunnel_conn: sosistab::Multiplex = tunnel_conn.multiplex();

        smol::spawn(async move {
            loop {
                let tunnel_conn: sosistab::RelConn = tunnel_conn.accept_conn().await.unwrap();
                let tcp_conn = smol::net::TcpStream::connect(tunnel_to).await.unwrap();

                smol::spawn(
                    smol::io::copy(tunnel_conn.clone(), tcp_conn.clone())
                        .race(smol::io::copy(tcp_conn, tunnel_conn)),
                )
                .detach();
            }
        })
        .detach();
    }
}

pub async fn async_server(tunnel_server: &str, tunnel_to: &str) -> anyhow::Result<()> {
    let listen = tunnel_server.parse::<std::net::SocketAddr>()?;
    let to = tunnel_to.parse::<std::net::SocketAddr>()?;
    let key = get_key().await;
    let pubkey_bytes = x25519_dalek::PublicKey::from(&key).to_bytes();
    let pubkey: String = {
        let mut pk: String = String::new();
        for i in 0..32 {
            let it = pubkey_bytes[i];
            let it: String = format!("{:02X}", it);
            pk.extend(it.chars());
        }
        pk
    };
    println!("You public key is {}", pubkey);
    server(key, listen, to).await;
    Ok(())
}

pub async fn async_client(
    tunnel_client: &str,
    tunnel_server: &str,
    pubkey: &str,
) -> anyhow::Result<()> {
    let listen = tunnel_client.parse::<std::net::SocketAddr>()?;
    let server = tunnel_server.parse::<std::net::SocketAddr>()?;
    let pk: [u8; 32] = {
        let mut key: [u8; 32] = [0u8; 32];
        let mut n: usize = 0;
        for i in (0..(pubkey.len())).step_by(2) {
            let it: &str = &pubkey[i..=i + 1];
            let it: u8 = u8::from_str_radix(it, 16).unwrap();
            key[n] = it;
            n += 1;
        }
        key
    };
    client(x25519_dalek::PublicKey::from(pk), listen, server).await;
    Ok(())
}

pub fn run_server(tunnel_server: &str, tunnel_to: &str) {
    smol::block_on(async {
        if let Err(e) = async_server(tunnel_server, tunnel_to).await {
            eprintln!("{:?}", e);
        }
    });
}

pub fn run_client(tunnel_client: &str, tunnel_server: &str, pubkey: &str) {
    smol::block_on(async {
        if let Err(e) = async_client(tunnel_client, tunnel_server, pubkey).await {
            eprintln!("{:?}", e);
        }
    });
}