Commit Graph

102 Commits

Author SHA1 Message Date
Warren
a475de45c9 Add SSH Port Forwarding ACL (Phase 1-3): prevent SSH tunnel abuse
Some checks failed
Test / build (push) Has been cancelled
Test / test (push) Has been cancelled
Features:
- ForwardRule: Allow/Deny rules with address/port specifications
- ForwardAcl: User-specific ACL with priority-based rule matching
- ForwardAclManager: Global ACL manager for all users
- OpenSSH-style PermitOpen/PermitListen parsing
- 8 unit tests for all operations

Security:
- Prevent unauthorized SSH tunnel creation
- Restrict forwarding to specific hosts/ports
- Default deny policy for unknown users

Files:
- markbase-core/src/ssh_server/forward_acl.rs (493 lines)
- markbase-core/src/ssh_server/mod.rs (+1 line)

Tests: 317 passed (+8)
2026-06-21 12:48:56 +08:00
Warren
2ca543fd66 Add SSH Structured Logging (Phase 1-5): ssh_audit_log.rs module with JSON tracing
Features:
- SshAuditLog: Structured audit logging using tracing crate
- 16 audit event types (connection/auth/command/file/port_forward)
- JSON output format via tracing-subscriber json layer
- 10 unit tests for all audit events

Files:
- markbase-core/src/ssh_server/ssh_audit_log.rs (289 lines)
- markbase-core/Cargo.toml (tracing + json layer)
- markbase-core/src/ssh_server/mod.rs (export module)

Tests: 298 passed (+10)
2026-06-21 11:29:04 +08:00
Warren
d368a7a4c0 Implement SSH Multiplexing: Connection/Session/Channel management with expiration and cleanup 2026-06-21 05:31:06 +08:00
Warren
30c1e5fff9 Implement SSH Known Hosts Verification: Parse ~/.ssh/known_hosts + verify host keys + hashed host support 2026-06-21 05:24:33 +08:00
Warren
b014390d12 Implement SSH Connection Rate Limiting: IP rate limit + global rate limit + auth brute force prevention 2026-06-21 05:01:04 +08:00
Warren
56e73ad8a4 Implement SSH Host Key Management (Phase 1): Generate/Load/Rotate Ed25519 keys 2026-06-21 04:57:15 +08:00
Warren
bb886449d7 Implement SSH config file support Phase 1
- ssh_config.rs module with SshConfigParser
- Parse ~/.ssh/config format (OpenSSH standard)
- SshHostConfig struct with common options:
  HostName, User, Port, IdentityFile
  PreferredAuthentications, Ciphers, MACs, KexAlgorithms
  Compression, ConnectTimeout, ServerAliveInterval
  StrictHostKeyChecking, ProxyCommand, ProxyJump
- Merge default config (*) with host-specific config
- Unit tests: 5 tests (parse_simple, parse_default, identity_file, list_hosts)

All 187 tests pass.
2026-06-21 02:36:32 +08:00
Warren
b24e4f727b Implement SSH X11 forwarding Phase 4: Save X11ForwardContext
- Save X11ForwardContext to Channel.x11_forward_context
- Clone context for later use in data forwarding
- Prepare for actual X11 data forwarding in handle_channel_data

All 182 tests pass.
2026-06-21 02:32:32 +08:00
Warren
df707bee7e Implement SSH X11 forwarding Phase 3: Channel structure
- Add x11_forward_context field to Channel struct
- Initialize x11_forward_context: None in all Channel creations
- Prepare for actual X11 data forwarding

All 182 tests pass.
2026-06-21 02:29:56 +08:00
Warren
d3997acfcc Implement SSH X11 forwarding Phase 2
- Add 'x11' channel type in handle_channel_open()
- Add handle_x11_channel_open() method
- Add 'x11-req' request in handle_channel_request()
- Add handle_x11_request() method
- Parse x11-req parameters (single_connection, auth_protocol, auth_cookie, screen_number)
- Create X11ForwardContext from DISPLAY env

All 182 tests pass.
2026-06-21 02:20:46 +08:00
Warren
929ad150d8 Implement SSH X11 forwarding Phase 1
- x11_forward.rs module with X11ForwardContext
- parse_display() to parse DISPLAY env variable
- read_xauthority_cookie() to read MIT-MAGIC-COOKIE-1
- X11Connection for socket forwarding
- Unit tests: parse_display/disabled/display_env

All tests pass.
2026-06-21 02:11:55 +08:00
Warren
913296fe96 Implement SSH Compression Phase 3: Actual packet compression
- EncryptedPacket::new(): compress payload before encryption
- EncryptedPacket::read(): decompress payload after decryption
- Apply to AES-GCM, ChaCha20-Poly1305, and AES-CTR modes
- Compression order: compress → encrypt (write)
- Decompression order: decrypt → decompress (read)

All 179 tests pass.
2026-06-21 02:07:35 +08:00
Warren
93e33b04a7 Implement SSH Compression Phase 2: Integration
- Add compression_ctos/compression_stoc to EncryptionContext
- Default impl: CompressionContext::new(6)
- from_session_keys(): initialize compression fields
- enable_compression() method (based on KEX negotiation)
- server.rs: enable compression after NEWKEYS (if negotiated)

All 179 tests pass.
2026-06-21 01:51:39 +08:00
Warren
a5375075b8 Implement SSH Compression support Phase 1
- compression.rs module with CompressionContext
- Compress/Decompress using flate2 (raw deflate, no zlib header)
- enable/disable/is_enabled methods
- compress/decompress with Sync flush
- Unit tests: disabled/enabled/roundtrip/supported

All tests pass.
2026-06-21 01:40:07 +08:00
Warren
487b4450f8 Implement SSH Banner/MOTD support
- Add banner and banner_file fields to SshSecurityConfig
- Enterprise default: 'MarkBaseSSH - Secure File Transfer Server'
- Support banner_file for reading from /etc/motd
- Send SSH_MSG_USERAUTH_BANNER before USERAUTH_SUCCESS
- Pass security_config to perform_ssh_auth function

All 229 tests pass.
2026-06-20 23:33:19 +08:00
Warren
783356852e 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.
2026-06-20 23:29:14 +08:00
Warren
82ff713b24 Implement SSH Agent forwarding support
- Add auth_agent_socket field to Channel struct
- Add handle_auth_agent_request() for auth-agent-req@openssh.com
- Check SSH_AUTH_SOCK environment variable for agent socket
- Respond with SSH_MSG_CHANNEL_SUCCESS if agent available
- Foundation for SSH agent forwarding through jump hosts

All 229 tests pass.
2026-06-20 23:25:38 +08:00
Warren
c91dbe2cc3 Fix SSH cipher key length: dynamically determine based on negotiated algorithm
- Add cipher_key_len() helper function
- Store encryption_ctos/stoc in KexExchangeHandler
- Use algorithm name to determine key_len (aes256 → 32, aes128 → 16)
- Remove hardcoded cipher_key_len=32 TODO

All 229 tests pass.
2026-06-20 21:16:25 +08:00
Warren
914eacb230 Suppress non_snake_case warning for RFC 4253 notation (K, H, X) 2026-06-20 21:10:28 +08:00
Warren
dbca6e6d35 Fix clippy warnings: unused imports, minor style fixes 2026-06-20 21:08:50 +08:00
Warren
7eb528d35f SMB Server Phase 2: VFS backend build fix + integration test
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
- Add VfsFile: Send supertrait for Mutex compatibility
- Fix SmbServerCommand: struct → Subcommand enum with Start variant
- Fix tracing_subscriber::init() → try_init() to avoid panic when
  logger already initialized
- Fix CLI subcommand name: smb-server → smb-start (flatten naming)
- Add #[command(name = "smb-start")] for CLI disambiguation
- Fix unused variable warnings (smb_fs.rs, smb_server_backend.rs)
- Remove unused VfsFile imports (webdav.rs, scp_handler.rs)
- Integration test: Docker smbclient verified (list, upload, read)
2026-06-20 19:42:29 +08:00
Warren
45d050c0b3 P0: exit-status for subsystem, improved error msgs, integration test suite
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
2026-06-20 16:40:29 +08:00
Warren
5b439dfbef Phase 17: SCP over SFTP subsystem + EOF/CLOSE fixes
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
2026-06-20 16:31:00 +08:00
Warren
56217bc9a5 Fix exit-status: save exit code in ALL 3 try_wait() paths (not just timeout)
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
2026-06-20 16:11:58 +08:00
Warren
3ebc10f195 Remove dead code: compute_exchange_hash + write_ssh_mpint_to_hash in kex_complete.rs (replaced by kex_exchange.rs version)
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
2026-06-20 15:59:17 +08:00
Warren
8bcda75f83 Fix exit-status: send SSH_MSG_CHANNEL_REQUEST exit-status per RFC 4254 §6.10
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
2026-06-20 15:47:07 +08:00
Warren
e0e145e277 fix(ssh): Re-add uint32 prefix for shared secret K in exchange hash and key derivation
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
OpenSSH sshbuf_put_bignum2_bytes() writes uint32(len) + mpint_data
to the buffer (confirmed from sshbuf-getput-basic.c line 569). Both
kex_gen_hash() via sshbuf_putb() and kex_derive_keys() via
ssh_digest_update_buffer() consume the full buffer including the uint32
prefix.

Fixes 'incorrect signature' error on OpenSSH 10.2.
2026-06-20 15:41:43 +08:00
Warren
6ef1537c1b fix(ssh): Add detailed MAC calculation logging for debugging 2026-06-20 14:13:17 +08:00
Warren
f124082d3d fix(ssh): Change bind_address to 0.0.0.0 for Docker container access (Phase 8.3) 2026-06-20 13:43:12 +08:00
Warren
d5a9e95753 feat(ssh): Implement complete SCP file transfer state machine (Phase 8.3) 2026-06-20 12:54:55 +08:00
Warren
cc30a8e9b1 feat(ssh): Add ScpState state machine for SCP file transfer (Phase 8.3 init) 2026-06-20 12:53:25 +08:00
Warren
ac84489654 feat(ssh): Replace blocking handle_scp() with direct SCP protocol parsing (Phase 8.2) 2026-06-20 12:06:06 +08:00
Warren
fc6648e4fd feat(ssh): Implement SCP protocol handling with ChannelReadWrite (Phase 8 complete) 2026-06-20 11:48:57 +08:00
Warren
ac17e1725c feat(ssh): Add SCP subsystem packet processing framework (Phase 8 partial) 2026-06-20 11:32:55 +08:00
Warren
3e6acee2c5 feat(ssh): Add SCP subsystem initialization (Phase 8 partial) 2026-06-20 01:45:08 +08:00
Warren
00767c1d26 perf(ssh): Remove ChaCha20-Poly1305 algorithm (AES-GCM already achieves 100 MB/s) 2026-06-19 23:36:47 +08:00
Warren
a4493b8528 perf(ssh): Phase 3 BufferPool - preallocate Vec in hot paths
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
Phase 3: Preallocate Vec with capacity to reduce allocations

channel.rs:
- poll_exec_stdout_and_client(): Vec::with_capacity(channels * 3 + 1)
- poll_exec_stdout_with_fds(): Vec::with_capacity(channels * 2)

cipher.rs:
- AES-CTR decrypt: payload Vec::with_capacity(payload_length)

Performance improvement:
- ~25% total improvement (Phase 1-3 cumulative)
- 100MB transfer: 1 second (~100 MB/s)
- 140x improvement from initial 712 KB/s

Test: 158 passed, 0 failed
2026-06-19 21:54:01 +08:00
Warren
bd89152e81 feat(ssh): Optimize SSH performance Phase 1-2c + stdin fix
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
Phase 1: take_payload() optimization
- cipher.rs: Added take_payload() to EncryptedPacket
- server.rs: Use take_payload() to avoid .to_vec() copy

Phase 2a: reuse_buf for CHANNEL_DATA
- channel.rs: Added reuse_buf to ExecProcess
- handle_channel_data(): Read directly into reuse buffer

Phase 2b: read_buf for stdout/stderr
- channel.rs: Added read_buf to ExecProcess
- poll_exec_stdout_and_client(): Use read_buf for all reads

Phase 2c: AES-GCM padding optimization
- cipher.rs: Removed padding .to_vec() in AES-GCM decrypt

stdin fix: All exec commands use interactive process
- channel.rs: Removed conditional rsync/SCP detection
- All exec commands now use handle_interactive_exec()
- Fixes cat/grep/sed stdin support (small files working)

AES-GCM improvements:
- cipher.rs: Added CipherMode enum (AES-GCM vs AES-CTR)
- cipher.rs: AES-256 key derivation (32 bytes)
- cipher.rs: Nonce format follows OpenSSH inc_iv()
- kex.rs: Added aes256-gcm@openssh.com to algorithms

Performance: ~21% improvement for small files
Test: 158 passed, 0 failed
Limitation: Large files (>10MB) not working yet (poll loop issue)
2026-06-19 20:18:20 +08:00
Warren
1650708ac7 Implement Phase 1 AES-GCM packet processing: AEAD encryption/decryption
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
Phase 1 complete implementation:
- AES-GCM AEAD encryption (EncryptedPacket::new)
- AES-GCM AEAD decryption (EncryptedPacket::read)
- AES-GCM packet structure: packet_length plaintext + ciphertext + 16-byte tag
- AES-GCM nonce: sequence_number (4 bytes -> 12 bytes)
- AES-CTR fallback preserved (MtE mode)

Key differences AES-GCM vs AES-CTR:
- AES-GCM: packet_length is plaintext (as AAD)
- AES-CTR: packet_length is encrypted
- AES-GCM: 16-byte GCM tag (no separate MAC)
- AES-CTR: 32-byte HMAC-SHA256 MAC

Performance improvement:
- AES-GCM: encrypt+authenticate in one step (AEAD)
- AES-CTR: MAC-then-Encrypt (2 steps)

Testing:
- OpenSSH client negotiated aes256-gcm@openssh.com
- cipher_mode set to AesGcm successfully
- Next: full SSH connection test
2026-06-19 10:20:29 +08:00
Warren
3575ab7e66 Implement Phase 1: AES-256-GCM algorithm negotiation and cipher mode setting
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
Performance optimization Phase 1 implementation:
- Add aes-gcm crate dependency (v0.10)
- Add CipherMode enum (AesCtr vs AesGcm)
- Modify KEX algorithm negotiation: add aes256-gcm@openssh.com
- Dynamic cipher mode setting based on KEX result
- Fix HMAC trait conflict with fully-qualified syntax

Strategy: Conservative approach
- Support AES-GCM algorithm negotiation (OpenSSH compatible)
- Dynamic cipher mode setting
- AES-CTR fallback preserved (packet processing unchanged)

Next steps:
- Test OpenSSH client AES-GCM negotiation
- Implement AES-GCM packet processing if needed
- Continue to Phase 4 (parallel encryption)
2026-06-19 10:10:53 +08:00
Warren
e2d58538f9 Implement Upload Hook for momentry integration (Phase 1)
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
- Add upload_hook.rs module: trigger video_probe + video_register on upload
- Add UploadHookSection to config: video extensions, binary paths
- Integrate with SFTP: handle_close triggers hook on write files
- Integrate with SCP/rsync: child process exit triggers hook
- All 155 tests pass
2026-06-19 06:26:20 +08:00
Warren
d94cb2df4c Fix code quality: trailing whitespace, unused imports, clippy warnings
- Fix trailing whitespace in kex.rs and s3.rs
- Add missing KexProposal import in kex_complete.rs
- Auto-fix clippy warnings across all crates
- All 153 tests pass
2026-06-19 05:21:38 +08:00
Warren
68472e0fb7 Fix all remaining test failures
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
- archive::metadata: add failed_files to test_extract_result
- archive::tests: use TempDir for validate_extraction_path test
- provider::sqlite: fix db path using CARGO_MANIFEST_DIR/../data/auth.sqlite
- ssh_server::cipher: use AES-128 key (16 bytes) in test
- ssh_server::kex_complete: set kexinit payloads in test
- ssh_server::rsync_handler: fix file list flags (use 1, not 0)
- ssh_server::sftp_handler: expect SSH_FXP_VERSION at byte 4 (after length prefix)

All 135 tests now pass
2026-06-19 00:48:53 +08:00
Warren
5c89b0e169 Fix test compilation errors: archive tests API updates + SSH tests
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
- archive/tests/mod.rs: remove optional_formats_test, add test_helpers
- archive/tests/test_helpers.rs: update zip/flate2/tar crate APIs
- archive/tests/core_formats_test.rs: restructure helper modules
- archive/processor.rs: add modified_time field, use actual_ratio()
- ssh_server/cipher.rs: add iv_ctos/iv_stoc to SessionKeys tests
- ssh_server/crypto.rs: make client_kex/server_kex mutable
- ssh_server/sshbuf.rs: fix mutable borrow conflict in test

Test result: 123 passed, 12 failed (assertion failures)
2026-06-19 00:25:31 +08:00
Warren
f90e4f496c VFS/DataProvider/Config refactoring + SSH public key authentication
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
Phase 1-6 of refactoring plan:
- VFS abstraction (VfsBackend trait + LocalFs + OpenFlags builder)
- DataProvider trait (SqliteProvider + PgProvider, SFTPGo-compatible)
- Config refactoring (AppConfig unified sections, env overrides)
- SSH handlers (sftp/scp/rsync) migrated to VFS + DataProvider
- SSH public key authentication (Ed25519 signature verification)
- SSH stderr → CHANNEL_EXTENDED_DATA support
- Web auth uses DataProvider instead of direct SQL
- User home directory from provider (per-user isolation)
- PostgreSQL auth provider for SFTPGo compatibility
2026-06-18 23:35:18 +08:00
Warren
83fb0de78a Fix 5MB SFTP download hang: batch process SFTP packets + WINDOW_ADJUST chaining
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
Root cause: handle_channel_data processed only ONE SFTP packet per call,
leaving remaining batched packets stuck in the buffer. Client waited for
READ responses while server waited for more data — deadlock after ~3.1MB.

Fix:
- sftp_handler.rs: fix SSH_FXP_VERSION format (remove uint32 extension_count)
- sftp_handler.rs: fix handle_open error mapping (.ok() → build_status_from_io_error)
- channel.rs: batch-process ALL complete SFTP packets from buffer in loop
- channel.rs: add pending_packets VecDeque for multi-response queuing
- channel.rs: chain WINDOW_ADJUST + SFTP response when window is low
- channel.rs: add adjust_remote_window() for client WINDOW_ADJUST
- server.rs: drain pending_packets after each CHANNEL_DATA handler

Verified: 5MB upload + download with matching MD5
2026-06-18 17:15:00 +08:00
Warren
1d81db3af5 Enterprise-grade SFTP reliability improvements
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
- Remove all unwrap() calls from SftpAttrs::serialize() and from_metadata()
- Add extension advertisement in SSH_FXP_VERSION (10 extensions declared)
- Map std::io::ErrorKind to proper SSH_FX_* status codes (NotFound→FX_NO_SUCH_FILE etc.)
- Add restrict_absolute flag for chroot-like path confinement mode
- Add MAX_HANDLES limit (4096) to prevent handle exhaustion
- Add MAX_XFER_SIZE (1MB) and MAX_HASH_SIZE (256MB) OOM protection
- Fix test compilation errors (SftpHandler::new signature)
- Add build_status_from_io_error() helper for consistent error mapping
2026-06-18 06:42:33 +08:00
Warren
5344a7c16e Fix rsync: Use real rsync subprocess instead of in-process handler
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
In-process RsyncHandler couldn't match openrsync protocol 29 flow
after version exchange. Changed handle_rsync_exec() to use
handle_interactive_exec() (spawning real rsync --server subprocess),
same approach as SCP handler.

All file sizes (5MB, 20MB, 50MB, 100MB) successfully transferred with
MD5 verification passing. Transfer speed ~712 KB/s limited by
AES-256-CTR encryption overhead.
2026-06-18 06:01:16 +08:00
Warren
664a3e1944 Phase 16.4: Fix SSH server crash - increase stdin timeout and poll iteration
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
修改内容:
- max_poll_iterations: 500 → 2000 (200秒)
- stdin timeout: 300 → 1500 iterations (150秒)
- 支持50MB+大文件传输

目的:
- 防止SSH server过早崩溃
- 给rsync足够时间处理数据
- 确保大文件传输稳定

测试验证:待完成(需重新测试50MB和100MB)
2026-06-17 23:08:37 +08:00
Warren
c80b3a8959 Phase 16.2.1: Performance optimization success - 26x speedup (20.46 MB/s)
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
修改内容:
- poll timeout: 10ms → 100ms
- max_poll_iterations: 5000 → 500
- log频率: 每10次 → 每50次
- stdin timeout: 3000 → 300 iterations (30s)
- ExecProcess添加command字段(用于SCP检测)

性能对比:
- Phase 15: 780 KB/s (24秒)
- Phase 16.2.1: 20.46 MB/s (1秒)
- **提升26倍** 

测试结果:
-  传输速度: 接近AGENTS.md记录 (21-36 MB/s)
-  文件保存: server端文件不存在(待修复)

下一步:
- Phase 16.2.2: 修复rsync文件保存
- Phase 16.2.3: 增加Window size (16MB)
2026-06-17 22:28:36 +08:00