Skip to content

Commit 3262ee3

Browse files
committed
chore: finalize PR with lint fixes and documentation
- Fix code formatting issues (handler.rs, session.rs) - Fix unused variable warning in test (s2 -> _s2) - Add comprehensive session management documentation - Document session_timeout configuration option - Add session management API examples
1 parent 5ba6146 commit 3262ee3

3 files changed

Lines changed: 105 additions & 3 deletions

File tree

docs/architecture/server-configuration.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ security:
192192
# Idle session timeout (seconds, 0 to disable)
193193
idle_timeout: 3600 # Default: 3600 (1 hour)
194194

195+
# Maximum session duration (seconds, 0 to disable)
196+
# Sessions are terminated after this duration regardless of activity
197+
session_timeout: 0 # Default: 0 (disabled)
198+
195199
# IP allowlist (CIDR notation, empty = allow all)
196200
# When configured, only connections from these ranges are allowed
197201
allowed_ips:
@@ -529,6 +533,100 @@ SSH Client Request Flow:
529533

530534
---
531535

536+
## Session Management
537+
538+
The server implements comprehensive session management with per-user limits, idle timeout detection, and session tracking.
539+
540+
### Session Configuration
541+
542+
Session management is configured through the `SessionConfig` structure:
543+
544+
```rust
545+
use bssh::server::session::SessionConfig;
546+
use std::time::Duration;
547+
548+
let config = SessionConfig::new()
549+
.with_max_sessions_per_user(10) // Max sessions per authenticated user
550+
.with_max_total_sessions(1000) // Max total concurrent sessions
551+
.with_idle_timeout(Duration::from_secs(3600)) // 1 hour idle timeout
552+
.with_session_timeout(Duration::from_secs(86400)); // 24 hour max duration
553+
```
554+
555+
### Session Limits
556+
557+
**Per-User Session Limits:**
558+
- Each authenticated user has a configurable maximum number of concurrent sessions
559+
- When a user exceeds their limit, authentication is rejected with an error
560+
- Default: 10 sessions per user
561+
562+
**Total Session Limits:**
563+
- The server enforces a global maximum number of concurrent sessions
564+
- New connections are rejected when the limit is reached
565+
- Default: 1000 total sessions (matches `max_connections`)
566+
567+
### Session Timeouts
568+
569+
**Idle Timeout:**
570+
- Sessions with no activity for the configured duration are marked as idle
571+
- The `cleanup_idle_sessions()` method removes idle unauthenticated sessions
572+
- Default: 1 hour (3600 seconds)
573+
574+
**Session Timeout:**
575+
- Optional maximum session duration regardless of activity
576+
- Sessions exceeding this duration are eligible for termination
577+
- Default: disabled (0)
578+
579+
### Session Activity Tracking
580+
581+
Each session tracks:
582+
- **Session ID**: Unique identifier for the session
583+
- **User**: Authenticated username (if authenticated)
584+
- **Peer Address**: Remote client IP and port
585+
- **Started At**: Timestamp of session creation
586+
- **Last Activity**: Timestamp of last activity (updated via `touch()`)
587+
- **Authentication State**: Whether the session is authenticated
588+
- **Auth Attempts**: Number of authentication attempts
589+
590+
### Session Statistics
591+
592+
The `SessionManager` provides session statistics:
593+
594+
```rust
595+
let stats = manager.get_stats();
596+
println!("Total sessions: {}", stats.total_sessions);
597+
println!("Authenticated: {}", stats.authenticated_sessions);
598+
println!("Unique users: {}", stats.unique_users);
599+
println!("Idle sessions: {}", stats.idle_sessions);
600+
```
601+
602+
### Admin Operations
603+
604+
The session manager supports administrative operations:
605+
606+
```rust
607+
// List all sessions
608+
let sessions = manager.list_sessions();
609+
610+
// List sessions for a specific user
611+
let user_sessions = manager.list_user_sessions("username");
612+
613+
// Force disconnect a session
614+
manager.kill_session(session_id);
615+
616+
// Force disconnect all sessions for a user
617+
let count = manager.kill_user_sessions("username");
618+
```
619+
620+
### Configuration Validation
621+
622+
The `SessionConfig::validate()` method checks for potentially problematic settings and returns warnings:
623+
624+
- Warning if `max_sessions_per_user` > `max_total_sessions` (per-user limit will never be reached)
625+
- Warning if `idle_timeout` is 0 (sessions immediately considered idle)
626+
- Warning if `session_timeout` < `idle_timeout` (sessions may be terminated before idle check)
627+
628+
---
629+
532630
**Related Documentation:**
533631
- [Server CLI Binary](../../ARCHITECTURE.md#server-cli-binary)
534632
- [SSH Server Module](../../ARCHITECTURE.md#ssh-server-module)

src/server/handler.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ use super::config::ServerConfig;
3333
use super::exec::CommandExecutor;
3434
use super::pty::PtyConfig as PtyMasterConfig;
3535
use super::security::AuthRateLimiter;
36-
use super::session::{ChannelState, PtyConfig, SessionError, SessionId, SessionInfo, SessionManager};
36+
use super::session::{
37+
ChannelState, PtyConfig, SessionError, SessionId, SessionInfo, SessionManager,
38+
};
3739
use super::sftp::SftpHandler;
3840
use super::shell::ShellSession;
3941
use crate::shared::rate_limit::RateLimiter;

src/server/session.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,9 @@ impl SessionConfig {
165165
}
166166

167167
if self.idle_timeout.as_secs() == 0 {
168-
warnings.push("idle_timeout is 0 - sessions will be immediately considered idle".to_string());
168+
warnings.push(
169+
"idle_timeout is 0 - sessions will be immediately considered idle".to_string(),
170+
);
169171
}
170172

171173
if let Some(session_timeout) = self.session_timeout {
@@ -1230,7 +1232,7 @@ mod tests {
12301232
let mut manager = SessionManager::with_config(config);
12311233

12321234
let s1 = manager.create_session(Some(test_addr())).unwrap();
1233-
let s2 = manager.create_session(Some(test_addr())).unwrap();
1235+
let _s2 = manager.create_session(Some(test_addr())).unwrap();
12341236

12351237
manager.authenticate_session(s1.id, "user1").unwrap();
12361238

0 commit comments

Comments
 (0)