mod connection;
mod forwarder;
mod socks;
mod stats;
pub use forwarder::DynamicForwarder;
pub use stats::DynamicForwarderStats;
#[cfg(test)]
pub use socks::{handle_socks4_connection, handle_socks5_connection};
#[cfg(test)]
mod tests {
use super::*;
use crate::{
forwarding::{ForwardingConfig, ForwardingType, SocksVersion},
ssh::tokio_client::{AuthMethod, Client, ServerCheckMethod},
};
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken;
use uuid::Uuid;
#[tokio::test]
#[ignore = "Requires SSH server connection"]
async fn test_dynamic_forwarder_creation() {
let spec = ForwardingType::Dynamic {
bind_addr: IpAddr::V4(Ipv4Addr::LOCALHOST),
bind_port: 1080,
socks_version: SocksVersion::V5,
};
let ssh_client = Arc::new(
Client::connect(
("127.0.0.1", 22),
"test_user",
AuthMethod::with_password("test"),
ServerCheckMethod::NoCheck,
)
.await
.unwrap(),
);
let config = ForwardingConfig::default();
let cancel_token = CancellationToken::new();
let (message_tx, _message_rx) = mpsc::unbounded_channel();
let session_id = Uuid::new_v4();
let forwarder = DynamicForwarder::new(
session_id,
spec,
ssh_client,
config,
cancel_token,
message_tx,
);
assert!(forwarder.is_ok());
let forwarder = forwarder.unwrap();
assert_eq!(forwarder.session_id, session_id);
assert_eq!(forwarder.socks_version, SocksVersion::V5);
}
#[test]
fn test_dynamic_forwarder_stats() {
let stats = DynamicForwarderStats::default();
stats.inc_accepted();
stats.inc_accepted();
stats.inc_accepted();
stats.inc_socks4();
stats.inc_socks5();
stats.inc_socks5();
stats.add_bytes(1024);
stats.add_bytes(2048);
assert_eq!(stats.total_accepted(), 3);
assert_eq!(
stats
.socks4_requests
.load(std::sync::atomic::Ordering::Relaxed),
1
);
assert_eq!(
stats
.socks5_requests
.load(std::sync::atomic::Ordering::Relaxed),
2
);
assert_eq!(stats.bytes_transferred(), 3072);
}
#[tokio::test]
#[ignore = "Requires SSH server connection"]
async fn test_socks_version_handling() {
for socks_version in [SocksVersion::V4, SocksVersion::V5] {
let spec = ForwardingType::Dynamic {
bind_addr: IpAddr::V4(Ipv4Addr::LOCALHOST),
bind_port: 1080,
socks_version,
};
let ssh_client = Arc::new(
Client::connect(
("127.0.0.1", 22),
"test_user",
AuthMethod::with_password("test"),
ServerCheckMethod::NoCheck,
)
.await
.unwrap(),
);
let config = ForwardingConfig::default();
let cancel_token = CancellationToken::new();
let (message_tx, _message_rx) = mpsc::unbounded_channel();
let session_id = Uuid::new_v4();
let forwarder = DynamicForwarder::new(
session_id,
spec,
ssh_client,
config,
cancel_token,
message_tx,
)
.unwrap();
assert_eq!(forwarder.socks_version, socks_version);
}
}
}