122 lines
3.3 KiB
Rust
122 lines
3.3 KiB
Rust
|
|
use std::collections::HashMap;
|
||
|
|
use std::sync::Arc;
|
||
|
|
|
||
|
|
use async_trait::async_trait;
|
||
|
|
use russh::keys::*;
|
||
|
|
use russh::server::{Msg, Server as _, Session};
|
||
|
|
use russh::*;
|
||
|
|
use tokio::sync::Mutex;
|
||
|
|
|
||
|
|
#[tokio::main]
|
||
|
|
async fn main() {
|
||
|
|
env_logger::builder()
|
||
|
|
.filter_level(log::LevelFilter::Debug)
|
||
|
|
.init();
|
||
|
|
|
||
|
|
let config = russh::server::Config {
|
||
|
|
inactivity_timeout: Some(std::time::Duration::from_secs(3600)),
|
||
|
|
auth_rejection_time: std::time::Duration::from_secs(3),
|
||
|
|
auth_rejection_time_initial: Some(std::time::Duration::from_secs(0)),
|
||
|
|
keys: vec![russh_keys::key::KeyPair::generate_ed25519()],
|
||
|
|
..Default::default()
|
||
|
|
};
|
||
|
|
let config = Arc::new(config);
|
||
|
|
let mut sh = Server {
|
||
|
|
clients: Arc::new(Mutex::new(HashMap::new())),
|
||
|
|
id: 0,
|
||
|
|
};
|
||
|
|
sh.run_on_address(config, ("0.0.0.0", 2222)).await.unwrap();
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Clone)]
|
||
|
|
struct Server {
|
||
|
|
clients: Arc<Mutex<HashMap<(usize, ChannelId), russh::server::Handle>>>,
|
||
|
|
id: usize,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Server {
|
||
|
|
async fn post(&mut self, data: CryptoVec) {
|
||
|
|
let mut clients = self.clients.lock().await;
|
||
|
|
for ((id, channel), ref mut s) in clients.iter_mut() {
|
||
|
|
if *id != self.id {
|
||
|
|
let _ = s.data(*channel, data.clone()).await;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl server::Server for Server {
|
||
|
|
type Handler = Self;
|
||
|
|
fn new_client(&mut self, _: Option<std::net::SocketAddr>) -> Self {
|
||
|
|
let s = self.clone();
|
||
|
|
self.id += 1;
|
||
|
|
s
|
||
|
|
}
|
||
|
|
fn handle_session_error(&mut self, _error: <Self::Handler as russh::server::Handler>::Error) {
|
||
|
|
eprintln!("Session error: {:#?}", _error);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[async_trait]
|
||
|
|
impl server::Handler for Server {
|
||
|
|
type Error = russh::Error;
|
||
|
|
|
||
|
|
async fn channel_open_session(
|
||
|
|
&mut self,
|
||
|
|
channel: Channel<Msg>,
|
||
|
|
session: &mut Session,
|
||
|
|
) -> Result<bool, Self::Error> {
|
||
|
|
{
|
||
|
|
let mut clients = self.clients.lock().await;
|
||
|
|
clients.insert((self.id, channel.id()), session.handle());
|
||
|
|
}
|
||
|
|
Ok(true)
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn auth_publickey(
|
||
|
|
&mut self,
|
||
|
|
_: &str,
|
||
|
|
key: &key::PublicKey,
|
||
|
|
) -> Result<server::Auth, Self::Error> {
|
||
|
|
dbg!(key);
|
||
|
|
Ok(server::Auth::Accept)
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn data(
|
||
|
|
&mut self,
|
||
|
|
channel: ChannelId,
|
||
|
|
data: &[u8],
|
||
|
|
session: &mut Session,
|
||
|
|
) -> Result<(), Self::Error> {
|
||
|
|
// Sending Ctrl+C ends the session and disconnects the client
|
||
|
|
if data == [3] {
|
||
|
|
return Err(russh::Error::Disconnect);
|
||
|
|
}
|
||
|
|
|
||
|
|
let data = CryptoVec::from(format!("Got data: {}\r\n", String::from_utf8_lossy(data)));
|
||
|
|
self.post(data.clone()).await;
|
||
|
|
session.data(channel, data);
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
async fn tcpip_forward(
|
||
|
|
&mut self,
|
||
|
|
address: &str,
|
||
|
|
port: &mut u32,
|
||
|
|
session: &mut Session,
|
||
|
|
) -> Result<bool, Self::Error> {
|
||
|
|
let handle = session.handle();
|
||
|
|
let address = address.to_string();
|
||
|
|
let port = *port;
|
||
|
|
tokio::spawn(async move {
|
||
|
|
let channel = handle
|
||
|
|
.channel_open_forwarded_tcpip(address, port, "1.2.3.4", 1234)
|
||
|
|
.await
|
||
|
|
.unwrap();
|
||
|
|
let _ = channel.data(&b"Hello from a forwarded port"[..]).await;
|
||
|
|
let _ = channel.eof().await;
|
||
|
|
});
|
||
|
|
Ok(true)
|
||
|
|
}
|
||
|
|
}
|