siranga/src/main.rs
2025-04-10 17:32:12 +02:00

64 lines
2.2 KiB
Rust

use std::{net::SocketAddr, path::Path};
use color_eyre::eyre::Context;
use dotenvy::dotenv;
use hyper::server::conn::http1::{self};
use hyper_util::rt::TokioIo;
use rand::rngs::OsRng;
use tokio::net::TcpListener;
use tracing::{error, info};
use tracing_subscriber::{EnvFilter, Registry, layer::SubscriberExt, util::SubscriberInitExt};
use tunnel_rs::{Server, Tunnels};
#[tokio::main]
async fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
dotenv().ok();
let env_filter = EnvFilter::try_from_default_env().or_else(|_| EnvFilter::try_new("info"))?;
let logger = tracing_subscriber::fmt::layer().compact();
Registry::default().with(logger).with(env_filter).init();
let key = if let Ok(path) = std::env::var("PRIVATE_KEY_FILE") {
russh::keys::PrivateKey::read_openssh_file(Path::new(&path))
.wrap_err_with(|| format!("failed to read ssh key: {path}"))?
} else {
russh::keys::PrivateKey::random(&mut OsRng, russh::keys::Algorithm::Ed25519)?
};
let port = 3000;
let domain = std::env::var("TUNNEL_DOMAIN").unwrap_or_else(|_| format!("localhost:{port}"));
let authz_address = std::env::var("AUTHZ_ENDPOINT")
.unwrap_or("http://localhost:9091/api/authz/forward-auth".into());
let tunnels = Tunnels::new(domain, authz_address);
let mut ssh = Server::new(tunnels.clone());
let addr = SocketAddr::from(([0, 0, 0, 0], 2222));
tokio::spawn(async move { ssh.run(key, addr).await });
info!("SSH is available on {addr}");
let addr = SocketAddr::from(([0, 0, 0, 0], port));
let listener = TcpListener::bind(addr).await?;
info!("HTTP is available on {addr}");
// TODO: Graceful shutdown
loop {
let (stream, _) = listener.accept().await?;
let io = TokioIo::new(stream);
let tunnels = tunnels.clone();
tokio::spawn(async move {
if let Err(err) = http1::Builder::new()
.preserve_header_case(true)
.title_case_headers(true)
.serve_connection(io, tunnels)
.with_upgrades()
.await
{
error!("Failed to serve connection: {err:?}");
}
});
}
}