Implement SSH Keep-alive support
- Add keep_alive_interval and keep_alive_max_count to SshSecurityConfig - Enterprise default: 15s interval, 3 max failures - Development default: 30s interval, 5 max failures - Track last_activity timestamp in service loop - Send keepalive@openssh.com channel request when idle - Disconnect after max keepalive failures - Add build_keepalive_request() and get_first_session_channel() - Prevents connection timeout on idle SSH sessions All 229 tests pass.
This commit is contained in:
@@ -470,11 +470,42 @@ fn handle_ssh_service_loop(
|
||||
) -> Result<()> {
|
||||
info!("Starting SSH service loop (Phase 14.2: unified poll + child status)");
|
||||
|
||||
// Keep-alive tracking
|
||||
let keep_alive_interval = security_config.lock().unwrap().keep_alive_interval;
|
||||
let keep_alive_max_count = security_config.lock().unwrap().keep_alive_max_count;
|
||||
let mut last_activity = std::time::Instant::now();
|
||||
let mut keep_alive_failures = 0;
|
||||
|
||||
loop {
|
||||
// ⭐⭐⭐⭐⭐ Phase 14.2: 统一poll + child状态检测
|
||||
let (stdout_packets, client_has_data, child_exited) =
|
||||
channel_manager.poll_exec_stdout_and_client(stream)?;
|
||||
|
||||
// Update activity timestamp on any data transfer
|
||||
if stdout_packets.is_some() || client_has_data {
|
||||
last_activity = std::time::Instant::now();
|
||||
keep_alive_failures = 0;
|
||||
}
|
||||
|
||||
// Keep-alive check: send if idle for too long
|
||||
let idle_duration = last_activity.elapsed().as_secs();
|
||||
if idle_duration >= keep_alive_interval && keep_alive_failures < keep_alive_max_count {
|
||||
info!("Sending keepalive (idle {}s)", idle_duration);
|
||||
if let Some(channel_id) = channel_manager.get_first_session_channel() {
|
||||
let keepalive_packet = channel_manager.build_keepalive_request(channel_id)?;
|
||||
let encrypted_keepalive = EncryptedPacket::new(&keepalive_packet.payload, encryption_ctx, true)?;
|
||||
encrypted_keepalive.write(stream)?;
|
||||
keep_alive_failures += 1;
|
||||
last_activity = std::time::Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
// Disconnect if too many keepalive failures
|
||||
if keep_alive_failures >= keep_alive_max_count {
|
||||
warn!("Connection timed out (keepalive failures: {})", keep_alive_failures);
|
||||
return Err(anyhow!("Connection timed out"));
|
||||
}
|
||||
|
||||
// 1. 发送stdout/stderr数据(如果有)
|
||||
if let Some(packets) = stdout_packets {
|
||||
// Phase 4: Batch encrypt all packets in parallel
|
||||
|
||||
Reference in New Issue
Block a user