Files
proxy/src/ssh.rs
Sienna Meridian Satterwhite a5810dd8a7 feat: configurable k8s resources, CSIC training pipeline, unified Dockerfile
- Make K8s namespace, TLS secret, and config ConfigMap names configurable
  via [kubernetes] config section (previously hardcoded to "ingress")
- Add CSIC 2010 dataset converter and auto-download for scanner training
- Unify Dockerfile for local and production builds (remove cross-compile path)
- Bake ML models directory into container image
- Update CSIC dataset URL to self-hosted mirror (src.sunbeam.pt)
- Fix rate_limit pipeline log missing fields
- Consolidate docs/README.md into root README.md

Signed-off-by: Sienna Meridian Satterwhite <sienna@sunbeam.pt>
2026-03-10 23:38:20 +00:00

59 lines
2.1 KiB
Rust

use tokio::io::copy_bidirectional;
use tokio::net::TcpStream;
use crate::dual_stack::DualStackTcpListener;
/// Listens on `listen` and proxies every TCP connection to `backend`.
/// Runs forever; intended to be spawned on a dedicated OS thread + Tokio runtime,
/// matching the pattern used for the cert/ingress watcher.
pub async fn run_tcp_proxy(listen: &str, backend: &str) {
// Parse the listen address to determine if it's IPv6 or IPv4
let ipv6_addr = if listen.starts_with('[') {
listen.to_string()
} else {
format!("[::]:{}", listen.split(':').next_back().unwrap_or("22"))
};
let ipv4_addr = if listen.contains(':') {
// Extract port from the original address
let port = listen.split(':').next_back().unwrap_or("22");
format!("0.0.0.0:{}", port)
} else {
"0.0.0.0:22".to_string()
};
let listener = match DualStackTcpListener::bind(&ipv6_addr, &ipv4_addr).await {
Ok(l) => {
tracing::info!(%listen, %backend, "SSH TCP proxy listening (dual-stack)");
l
}
Err(e) => {
tracing::error!(error = %e, %listen, "SSH TCP proxy: bind failed");
return;
}
};
loop {
match listener.accept().await {
Ok((mut socket, peer_addr)) => {
let backend = backend.to_string();
tokio::spawn(async move {
match TcpStream::connect(&backend).await {
Ok(mut upstream) => {
if let Err(e) = copy_bidirectional(&mut socket, &mut upstream).await {
tracing::debug!(error = %e, %peer_addr, "ssh: session ended");
}
}
Err(e) => {
tracing::error!(error = %e, %peer_addr, %backend, "ssh: upstream connect failed");
}
}
});
}
Err(e) => {
tracing::error!(error = %e, "ssh: accept failed");
}
}
}
}