feat: added the ability to test a connection
This commit is contained in:
parent
fb98d062ef
commit
022340ec95
@ -18,11 +18,11 @@ mod commands;
|
|||||||
mod shell;
|
mod shell;
|
||||||
|
|
||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
config: ClientConfig,
|
pub(crate) config: ClientConfig,
|
||||||
foreign_sign_pubkey: ed25519_dalek::PublicKey,
|
pub(crate) foreign_sign_pubkey: ed25519_dalek::PublicKey,
|
||||||
foreign_enc_pubkey: ecies_ed25519::PublicKey,
|
pub(crate) foreign_enc_pubkey: ecies_ed25519::PublicKey,
|
||||||
socket: Arc<UdpSocket>,
|
pub(crate) socket: Arc<UdpSocket>,
|
||||||
ip: SocketAddr,
|
pub(crate) ip: SocketAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
|
|||||||
118
sparse-05/sparse-05-client/src/commands/connecttest.rs
Normal file
118
sparse-05/sparse-05-client/src/commands/connecttest.rs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
use std::{
|
||||||
|
io::{self, Write},
|
||||||
|
net::SocketAddr,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
|
use ed25519_dalek::{Signature, Signer, Verifier};
|
||||||
|
use sparse_05_common::messages::{
|
||||||
|
Capabilities, Command, Response, CONNECTED_MESSAGE, CONNECT_MESSAGE,
|
||||||
|
};
|
||||||
|
use tokio::{fs, net::UdpSocket};
|
||||||
|
|
||||||
|
use crate::configs::ClientConfig;
|
||||||
|
|
||||||
|
pub async fn connecttest(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
||||||
|
let config = fs::read(&config).await?;
|
||||||
|
let config: ClientConfig = rmp_serde::from_slice(&config)?;
|
||||||
|
|
||||||
|
let remote = Arc::new(UdpSocket::bind("0.0.0.0:0").await?);
|
||||||
|
|
||||||
|
let connect_signature = config.keypair.sign(CONNECT_MESSAGE).to_bytes();
|
||||||
|
let connect_msg = &[&connect_signature, CONNECT_MESSAGE].concat();
|
||||||
|
|
||||||
|
let mut counter = 0;
|
||||||
|
|
||||||
|
let (foreign_sign_pubkey, foreign_enc_pubkey, capabilities) = loop {
|
||||||
|
if counter > 25 {
|
||||||
|
bail!("could not connect to server");
|
||||||
|
}
|
||||||
|
|
||||||
|
print!(
|
||||||
|
"\rConnecting{}",
|
||||||
|
match counter % 3 {
|
||||||
|
2 => ".. ",
|
||||||
|
1 => ". ",
|
||||||
|
_ => "...",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
|
||||||
|
remote.send_to(connect_msg, ip).await?;
|
||||||
|
|
||||||
|
let mut buf = [0u8; 2000];
|
||||||
|
|
||||||
|
match tokio::time::timeout(
|
||||||
|
std::time::Duration::from_millis(250),
|
||||||
|
remote.recv_from(&mut buf),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(packet) => {
|
||||||
|
let (count, addr) = packet?;
|
||||||
|
|
||||||
|
if addr != ip {
|
||||||
|
bail!("received response from wrong source");
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = &buf[..count];
|
||||||
|
|
||||||
|
if data.len() < 65 {
|
||||||
|
bail!("could not get signature from server");
|
||||||
|
}
|
||||||
|
|
||||||
|
let signature: [u8; 64] = data[..64].try_into().unwrap();
|
||||||
|
let data = &data[64..];
|
||||||
|
|
||||||
|
let Ok(foreign_keys) = ecies_ed25519::decrypt(&config.enc_privkey, data) else {
|
||||||
|
counter += 1;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if foreign_keys.len()
|
||||||
|
< ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH
|
||||||
|
{
|
||||||
|
bail!("could not get public keys from the server");
|
||||||
|
}
|
||||||
|
|
||||||
|
let foreign_sign_pubkey = ed25519_dalek::PublicKey::from_bytes(
|
||||||
|
&foreign_keys[..ed25519_dalek::PUBLIC_KEY_LENGTH],
|
||||||
|
)?;
|
||||||
|
let foreign_enc_pubkey = ecies_ed25519::PublicKey::from_bytes(
|
||||||
|
&foreign_keys[ed25519_dalek::PUBLIC_KEY_LENGTH
|
||||||
|
..(ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH)],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let capabilities: Capabilities = rmp_serde::from_slice(
|
||||||
|
&foreign_keys
|
||||||
|
[(ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH)..],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
foreign_sign_pubkey.verify(data, &Signature::from(signature))?;
|
||||||
|
|
||||||
|
break (foreign_sign_pubkey, foreign_enc_pubkey, capabilities);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let connection = Arc::new(crate::commands::connect::Connection {
|
||||||
|
config,
|
||||||
|
foreign_enc_pubkey,
|
||||||
|
foreign_sign_pubkey,
|
||||||
|
socket: Arc::clone(&remote),
|
||||||
|
ip,
|
||||||
|
});
|
||||||
|
|
||||||
|
remote
|
||||||
|
.send_to(&connection.encrypt_and_sign(CONNECTED_MESSAGE)?, ip)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
println!("\rConnected! ");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
pub mod connect;
|
pub mod connect;
|
||||||
|
pub mod connecttest;
|
||||||
pub mod generate;
|
pub mod generate;
|
||||||
|
|||||||
@ -15,5 +15,6 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
commands::generate::generate(name, port, target).await
|
commands::generate::generate(name, port, target).await
|
||||||
}
|
}
|
||||||
Command::Connect { config, ip } => commands::connect::connect(config, ip).await,
|
Command::Connect { config, ip } => commands::connect::connect(config, ip).await,
|
||||||
|
Command::ConnectTest { config, ip } => commands::connecttest::connecttest(config, ip).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,13 @@ pub enum Command {
|
|||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
config: PathBuf,
|
config: PathBuf,
|
||||||
|
|
||||||
|
#[structopt(parse(try_from_str = to_socket_addr))]
|
||||||
|
ip: SocketAddr,
|
||||||
|
},
|
||||||
|
ConnectTest {
|
||||||
|
#[structopt(parse(from_os_str))]
|
||||||
|
config: PathBuf,
|
||||||
|
|
||||||
#[structopt(parse(try_from_str = to_socket_addr))]
|
#[structopt(parse(try_from_str = to_socket_addr))]
|
||||||
ip: SocketAddr,
|
ip: SocketAddr,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user