pub(crate) mod args;
pub(crate) mod config;
pub(crate) mod errors;
pub(crate) mod honeypot;
pub(crate) mod keygen;
pub(crate) mod relay;
pub(crate) mod shared;
pub(crate) mod signals;
pub(crate) mod ssh;
use crate::args::Args;
use crate::errors::*;
use crate::shared::Shared;
use clap::Parser;
use env_logger::Env;
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
use std::sync::Arc;
const DEFAULT_SSHD_BIND_ADDR: SocketAddr = SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 2);
#[tokio::main]
async fn main() -> Result<()> {
let args = Args::parse();
let log_level = match args.verbose {
0 => "hussh=info",
1 => "hussh=debug",
2 => "debug",
3 => "hussh=trace,debug",
_ => "trace",
};
env_logger::init_from_env(Env::default().default_filter_or(log_level));
if args.keygen {
let key = keygen::keygen_str()?;
println!("{}", key.as_str().trim_end());
Ok(())
} else {
let config = args.config().await?;
let missing_configuration =
config.rules.is_empty() && config.honeypot == Default::default();
let bind_addr = config
.sshd
.bind_addr(&args)
.unwrap_or(DEFAULT_SSHD_BIND_ADDR);
let (shared, relay_rx, honeypot_rx) = Shared::from_config(config);
let key = keygen::init_from_path(&args.data_dir.join("sshd.key")).await?;
let shared = Arc::new(shared);
let mut server = ssh::server::SshServer::new(shared.clone());
let sighup = signals::sighup(shared.clone(), args);
if missing_configuration {
warn!(
"No rules or honeypot configuration found, the daemon will not do anything useful"
);
}
tokio::select! {
res = relay::run(relay_rx) => res,
res = server.run(key, bind_addr) => res,
res = honeypot::logger(shared, honeypot_rx) => Ok(res),
res = sighup => Ok(res),
res = signals::sigterm() => Ok(res),
}
}
}