1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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 run_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 run_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 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);
    run_server(key, listen, to).await;
    Ok(())
}

pub async fn 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
    };
    run_client(x25519_dalek::PublicKey::from(pk), listen, server).await;
    Ok(())
}