[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81797":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":15,"stars30d":15,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":10,"pushedAt":10,"updatedAt":32,"readmeContent":33,"aiSummary":34,"trendingCount":15,"starSnapshotCount":15,"syncStatus":14,"lastSyncTime":35,"discoverSource":36},81797,"ssh_proxy","mac119\u002Fssh_proxy","mac119","🛡️ A high-performance SSH proxy gateway built in Rust — unified authentication, per-user access control (ACL), full session audit logging, and terminal replay. Secure your infrastructure without modifying target servers.","",null,"Rust",41,8,2,0,42.86,"MIT License",false,"main",true,[22,23,24,25,26,27,28,29,30,31],"access-control","audit-log","bastion-host","gateway","proxy","rust","security","session-recording","ssh","tokio","2026-06-12 04:01:35","```\n    ┌─────────────────────────────────┐\n    │         ╔═══╗                   │\n    │         ║ ⬡ ║  SSH GUARD        │\n    │         ╚═══╝                   │\n    │    ┌───┐       ┌───┐  ┌───┐    │\n    │    │ U ├──→ P ─┤ T │  │ T │    │\n    │    └───┘  ↕    └───┘  └───┘    │\n    │         AUDIT                   │\n    └─────────────────────────────────┘\n```\n\n# 🛡️ SSH Guard Proxy\n\n**A high-performance SSH proxy gateway built in Rust for security auditing, access control, and session recording.**\n\n[![Rust](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FRust-1.70%2B-orange?logo=rust)](https:\u002F\u002Fwww.rust-lang.org\u002F)\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-blue.svg)](LICENSE)\n[![tokio](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fasync-tokio-blue)](https:\u002F\u002Ftokio.rs\u002F)\n\n*Every keystroke recorded. Every connection authorized. Every session auditable.*\n\n\u003C\u002Fdiv>\n\n---\n\n## 🎯 Why SSH Guard Proxy?\n\nIn modern infrastructure, direct SSH access to production servers is a **security risk**. SSH Guard Proxy solves this by acting as a **single point of entry** — a bastion host that enforces authentication, authorization, and full audit logging for every SSH session.\n\n### The Problem\n\n- Developers SSH directly into production servers with no oversight\n- No centralized record of who did what and when\n- Shared credentials make accountability impossible\n- Revoking access requires touching every server\n\n### The Solution\n\n```\nDeveloper → SSH Guard Proxy → Target Server\n                ↓\n          Audit Log (every keystroke)\n```\n\n---\n\n## ✨ Features\n\n| Feature | Description |\n|---------|-------------|\n| 🔐 **Unified Authentication** | Password (Argon2id) and public key auth at the gateway |\n| 🎛️ **Access Control (ACL)** | Per-user host access policies — who can access what |\n| 📝 **Full Audit Logging** | Every input\u002Foutput recorded in JSON Lines format |\n| 🎬 **Session Recording** | Asciicast v2 format — replay any session with `asciinema` |\n| 🚫 **Command Filtering** | Blacklist\u002Fwhitelist mode — block dangerous commands in real-time |\n| 📂 **SCP\u002FSFTP Auditing** | Full file transfer logging with filenames, sizes, and direction |\n| 👁️ **Session Sharing** | Multiple admins can watch a live session in real-time (read-only) |\n| ⚡ **High Performance** | Built on Rust + Tokio async runtime — minimal overhead |\n| 🏗️ **Zero Target Changes** | No agent or modification needed on target servers |\n| 🔑 **Host Key Auto-generation** | Ed25519 host keys generated on first run |\n| 🚦 **Connection Limiting** | Max session control and auth failure lockout |\n\n---\n\n## 🏗️ Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                      SSH Guard Proxy                              │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                   │\n│   User ──SSH──→ [SSH Server] ──→ [Auth & ACL] ──→ [Session Mgr]  │\n│                                                        │          │\n│                                                        ▼          │\n│                  [Audit Logger] ◀────────────── [SSH Client] ──→ Target\n│                       │                                           │\n│                       ▼                                           │\n│                 logs\u002Faudit.jsonl                                   │\n│                                                                   │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n### Data Flow\n\n1. User connects: `ssh admin@proxy -p 2222`\n2. Proxy authenticates the user (password or public key)\n3. User selects a target host from the authorized list\n4. Proxy establishes SSH connection to target\n5. All data is bidirectionally forwarded **and** logged\n6. Session ends → audit record finalized\n\n---\n\n## 🚀 Quick Start\n\n### Installation\n\n#### Option 1: Download Pre-built Binary (Recommended)\n\nDownload the latest release from the [Releases page](https:\u002F\u002Fgithub.com\u002Fmac119\u002Fssh_proxy\u002Freleases):\n\n```bash\n# Download and extract (example for macOS arm64)\ncurl -L https:\u002F\u002Fgithub.com\u002Fmac119\u002Fssh_proxy\u002Freleases\u002Fdownload\u002Fv0.1.0\u002Fssh-guard-proxy-v0.1.0-darwin-arm64.tar.gz | tar xz\n\n# Or manually download, extract, and set permissions\nchmod +x ssh_proxy hash_password\n```\n\nThe release package includes:\n- `ssh_proxy` — Main proxy binary\n- `hash_password` — Password hash generator tool\n- `config\u002F` — Configuration templates\n\n#### Option 2: Build from Source\n\nRequires **Rust 1.70+** (install via [rustup](https:\u002F\u002Frustup.rs\u002F)):\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fmac119\u002Fssh_proxy.git\ncd ssh_proxy\ncargo build --release\n# Binaries at: target\u002Frelease\u002Fssh_proxy, target\u002Frelease\u002Fhash_password\n```\n\n### Configure\n\n#### 1. Proxy Settings (`config\u002Fproxy.toml`)\n\n```toml\n[server]\nlisten_address = \"0.0.0.0\"\nlisten_port = 2222\nhost_key_path = \"config\u002Fhost_key\"\n\n[session]\nidle_timeout_secs = 1800\nmax_sessions = 100\n\n[audit]\nlog_dir = \"logs\"\nrecord_session = true\n\n[security]\nmax_auth_attempts = 3\nlockout_duration_secs = 300\n```\n\n#### 2. Add Users (`config\u002Fusers.toml`)\n\nGenerate a password hash first:\n\n```bash\n.\u002Fhash_password 'YourSecurePassword'\n# Output: $argon2id$v=19$m=19456,t=2,p=1$...\n```\n\nThen add to config:\n\n```toml\n[[users]]\nname = \"admin\"\npassword_hash = \"$argon2id$v=19$m=19456,t=2,p=1$...\"\npublic_keys = []\nallowed_hosts = [\"*\"]  # Access to all hosts\n\n[[users]]\nname = \"developer\"\npassword_hash = \"$argon2id$v=19$m=19456,t=2,p=1$...\"\npublic_keys = [\"ssh-ed25519 AAAAC3Nza...\"]\nallowed_hosts = [\"web-01\", \"web-02\"]  # Restricted access\n```\n\n#### 3. Add Target Hosts (`config\u002Fhosts.toml`)\n\n```toml\n[[hosts]]\nname = \"web-01\"\naddress = \"192.168.1.10\"\nport = 22\nusername = \"deploy\"\nauth_method = \"key\"\nprivate_key_path = \"config\u002Fkeys\u002Fweb-01\"\n\n[[hosts]]\nname = \"db-01\"\naddress = \"10.0.0.50\"\nport = 22\nusername = \"dbadmin\"\nauth_method = \"password\"\npassword = \"encrypted:your_password_here\"\n```\n\n### Run\n\n```bash\n# Foreground (for testing)\n.\u002Fssh_proxy\n\n# Background with nohup\nnohup .\u002Fssh_proxy > \u002Fvar\u002Flog\u002Fssh_proxy.log 2>&1 &\n\n# Background with output to file (recommended for debugging)\n.\u002Fssh_proxy >> logs\u002Fproxy.log 2>&1 &\necho $! > ssh_proxy.pid   # Save PID for later stop\n\n# Stop the proxy\nkill $(cat ssh_proxy.pid)\n```\n\n> **Note**: In production, use **systemd** (see [Production Deployment](#-production-deployment) below) for auto-restart, log management, and proper signal handling.\n\n### Connect\n\n```bash\nssh admin@your-proxy-host -p 2222\n```\n\nYou'll see:\n\n```\nWelcome, admin! Available hosts:\n─────────────────────────────────────\n  [1] web-01 (192.168.1.10:22)\n  [2] web-02 (192.168.1.11:22)\n  [3] db-01 (10.0.0.50:22)\n─────────────────────────────────────\nSelect host number: \n```\n\nSelect a host and you're in — fully transparent, fully audited.\n\n### File Transfer (SCP\u002FSFTP)\n\nSSH Guard Proxy supports **SCP and SFTP file transfers** with full audit logging. All file transfers are recorded — including filenames, sizes, direction, and timestamps.\n\n#### Upload a File\n\n```bash\n# Upload to the default target host (first allowed host)\nscp -P 2222 myfile.txt admin@proxy-host:\u002Ftmp\u002F\n\n# Upload to a specific target host (use user%host format)\nscp -P 2222 myfile.txt admin%db-server-01@proxy-host:\u002Ftmp\u002F\n\n# Recursive directory upload\nscp -r -P 2222 .\u002Fmy-folder admin%web-server-01@proxy-host:\u002Fopt\u002F\n```\n\n#### Download a File\n\n```bash\n# Download from the default target host\nscp -P 2222 admin@proxy-host:\u002Fetc\u002Fhosts .\u002F\n\n# Download from a specific target host\nscp -P 2222 admin%db-server-01@proxy-host:\u002Fvar\u002Flog\u002Fapp.log .\u002F\n```\n\n#### Legacy SCP Mode\n\nModern OpenSSH (9.0+) uses SFTP by default for `scp` commands. Both modes are fully supported:\n\n```bash\n# Default (SFTP mode) — works out of the box\nscp -P 2222 file.txt admin@proxy-host:\u002Ftmp\u002F\n\n# Force legacy SCP protocol (if needed)\nscp -O -P 2222 file.txt admin@proxy-host:\u002Ftmp\u002F\n```\n\n#### Target Host Selection\n\n| Method | Example | Description |\n|--------|---------|-------------|\n| Default | `admin@proxy` | Uses the first allowed host from ACL |\n| Explicit | `admin%db-server-01@proxy` | Specifies exact target host by name |\n\n#### SCP Audit Log Events\n\nAll file transfers generate audit entries:\n\n```json\n{\"event\":\"scp_session_start\",\"session_id\":\"...\",\"user\":\"admin\",\"direction\":\"upload\",\"target_host\":\"db-server-01\",\"remote_path\":\"\u002Ftmp\u002F\"}\n{\"event\":\"scp_file_transfer\",\"session_id\":\"...\",\"user\":\"admin\",\"direction\":\"upload\",\"filename\":\"myfile.txt\",\"size\":10240,\"mode\":\"0644\"}\n```\n\n---\n\n### Session Sharing (Live Watch)\n\nAdmins with watch permission can observe another user's active session in real-time (read-only).\n\n#### Enable Watch Permission\n\n```toml\n# config\u002Fusers.toml\n[[users]]\nname = \"admin\"\ncan_watch_sessions = true\nwatch_allowed_users = [\"*\"]  # \"*\" = all users, or specific names\n```\n\n#### Usage\n\n1. Connect to the proxy: `ssh admin@proxy-host -p 2222`\n2. At the host selection menu, enter `w`:\n   ```\n   Welcome, admin! Available hosts:\n   ─────────────────────────────────────\n     [1] web-server-01 (192.168.1.10:22)\n   ─────────────────────────────────────\n     [w] Watch active session\n   ─────────────────────────────────────\n   Select host number: w\n   ```\n3. Select a session to watch:\n   ```\n   Active sessions:\n   ─────────────────────────────────────\n     [1] user=developer target=web-server-01 (5m ago, 0 watchers)\n   ─────────────────────────────────────\n   Select session number (q to cancel): 1\n   ```\n4. You now see the session output in real-time. Press `Ctrl+C` to stop watching.\n\n#### Notes\n- Watchers are **read-only** — no input is sent to the watched session\n- Multiple admins can watch the same session simultaneously\n- All watch events are audit-logged (`session_watch_start`, `session_watch_end`)\n\nDemo \n* log in to the remote server\n\u003Cimg width=\"2264\" height=\"540\" alt=\"image\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F2d360d5e-6a0b-4cf7-9401-de7a31609ace\" \u002F>\n\n* then execute `ls` command\n\u003Cimg width=\"1274\" height=\"150\" alt=\"image\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F6e812cbb-3584-4073-ac9f-b2948f58c0d7\" \u002F>\n\n* Duplicate the terminal and  log in to the  ssh-proxy server. We will notice a `ls` command is being executed\n\u003Cimg width=\"1764\" height=\"814\" alt=\"image\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fb77b5eb3-d814-4323-94a9-e4df09008673\" \u002F>\n\n\n---\n\n## 📊 Audit Logs\n\nAll audit data is stored in `logs\u002Faudit.jsonl` in append-only JSON Lines format.\n\n### Log Events\n\n| Event | Description |\n|-------|-------------|\n| `auth_success` | Successful authentication |\n| `auth_failure` | Failed authentication attempt |\n| `session_start` | User connected to a target host |\n| `session_end` | Session terminated |\n| `data` (input) | User keystrokes \u002F commands |\n| `data` (output) | Server responses |\n| `command_blocked` | Command rejected by filter |\n| `scp_session_start` | SCP\u002FSFTP transfer session initiated |\n| `scp_file_transfer` | File transferred (name, size, direction) |\n| `session_watch_start` | Admin started watching a session |\n| `session_watch_end` | Admin stopped watching (with duration) |\n\n### Example Log Entries\n\n```json\n{\"event\":\"auth_success\",\"timestamp\":\"2026-05-05T07:10:00Z\",\"user\":\"admin\",\"peer_addr\":\"10.0.1.5:54321\",\"method\":\"password\"}\n{\"event\":\"session_start\",\"timestamp\":\"2026-05-05T07:10:05Z\",\"session_id\":\"a1b2c3d4\",\"user\":\"admin\",\"peer_addr\":\"10.0.1.5:54321\",\"target_host\":\"web-01\",\"target_addr\":\"192.168.1.10\"}\n{\"event\":\"data\",\"timestamp\":\"2026-05-05T07:10:10Z\",\"session_id\":\"a1b2c3d4\",\"direction\":\"input\",\"data_base64\":\"bHMgLWxhCg==\",\"data_len\":7}\n{\"event\":\"data\",\"timestamp\":\"2026-05-05T07:10:10Z\",\"session_id\":\"a1b2c3d4\",\"direction\":\"output\",\"data_base64\":\"dG90YWwgNDgK...\",\"data_len\":256}\n{\"event\":\"session_end\",\"timestamp\":\"2026-05-05T07:45:00Z\",\"session_id\":\"a1b2c3d4\"}\n```\n\n### Decoding Commands from Logs\n\n```bash\n# View all input commands from a session\ngrep '\"direction\":\"input\"' logs\u002Faudit.jsonl | \\\n  jq -r '.data_base64' | \\\n  while read line; do echo \"$line\" | base64 -d; done\n\n# Find who connected today\ngrep '\"event\":\"session_start\"' logs\u002Faudit.jsonl | \\\n  grep \"$(date +%Y-%m-%d)\" | \\\n  jq '{user, target_host, timestamp}'\n\n# Count failed logins\ngrep '\"event\":\"auth_failure\"' logs\u002Faudit.jsonl | wc -l\n```\n\n### Session Replay\n\nSessions are recorded in [asciicast v2](https:\u002F\u002Fgithub.com\u002Fasciinema\u002Fasciinema\u002Fblob\u002Fdevelop\u002Fdoc\u002Fasciicast-v2.md) format:\n\n```bash\n# Replay a recorded session\nasciinema play logs\u002Fsessions\u002F\u003Csession_id>.cast\n```\n\n---\n\n## 🏢 Production Deployment\n\n### Systemd Service\n\nCreate `\u002Fetc\u002Fsystemd\u002Fsystem\u002Fssh-guard-proxy.service`:\n\n```ini\n[Unit]\nDescription=SSH Guard Proxy\nAfter=network.target\n\n[Service]\nType=simple\nUser=sshproxy\nGroup=sshproxy\nWorkingDirectory=\u002Fopt\u002Fssh_proxy\nExecStart=\u002Fopt\u002Fssh_proxy\u002Fssh_proxy\nRestart=always\nRestartSec=5\n\n# Security hardening\nNoNewPrivileges=true\nProtectSystem=strict\nReadWritePaths=\u002Fopt\u002Fssh_proxy\u002Flogs\n\n[Install]\nWantedBy=multi-user.target\n```\n\n```bash\nsudo systemctl enable ssh-guard-proxy\nsudo systemctl start ssh-guard-proxy\n```\n\n### File Permissions\n\n```bash\nchmod 600 config\u002Fhost_key\nchmod 600 config\u002Fkeys\u002F*\nchmod 644 config\u002F*.toml\nchmod 700 logs\u002F\n```\n\n### Log Rotation\n\nAdd to `\u002Fetc\u002Flogrotate.d\u002Fssh-guard-proxy`:\n\n```\n\u002Fopt\u002Fssh_proxy\u002Flogs\u002Faudit.jsonl {\n    daily\n    rotate 90\n    compress\n    delaycompress\n    missingok\n    notifempty\n    copytruncate\n}\n```\n\n### Firewall\n\n```bash\n# Only expose the proxy port\nufw allow 2222\u002Ftcp\n# Block direct SSH to target hosts from outside\nufw deny from any to 192.168.1.0\u002F24 port 22\n```\n\n---\n\n## 📁 Project Structure\n\n```\nssh_proxy\u002F\n├── Cargo.toml                 # Dependencies & build config\n├── config\u002F\n│   ├── proxy.toml             # Main proxy configuration\n│   ├── users.toml             # User accounts & ACL\n│   ├── hosts.toml             # Target host definitions\n│   └── host_key              # Auto-generated Ed25519 host key\n├── src\u002F\n│   ├── main.rs               # Entry point\n│   ├── config.rs             # Configuration loading\n│   ├── server\u002F\n│   │   ├── mod.rs            # TCP listener & session spawning\n│   │   └── handler.rs        # SSH protocol handler (auth, data relay)\n│   ├── client\u002F\n│   │   └── mod.rs            # SSH client (connects to targets)\n│   ├── auth\u002F\n│   │   ├── mod.rs            # Authentication (Argon2id, pubkey)\n│   │   └── acl.rs            # Access control logic\n│   ├── session\u002F\n│   │   └── mod.rs            # Session lifecycle management\n│   └── audit\u002F\n│       ├── mod.rs            # Audit event logger\n│       └── recorder.rs       # Asciicast session recorder\n├── src\u002Fbin\u002F\n│   └── hash_password.rs      # CLI tool to generate password hashes\n└── logs\u002F                      # Audit output directory\n```\n\n---\n\n## 🔧 Technology Stack\n\n| Component | Choice | Rationale |\n|-----------|--------|-----------|\n| Language | **Rust** | Memory safety, zero-cost abstractions, fearless concurrency |\n| SSH Protocol | **russh** | Native async SSH implementation (server + client) |\n| Async Runtime | **Tokio** | Industry-standard, battle-tested async runtime |\n| Password Hashing | **Argon2id** | Winner of Password Hashing Competition |\n| Logging | **tracing** | Structured, async-aware instrumentation |\n| Config | **TOML + serde** | Human-readable, type-safe configuration |\n\n---\n\n## 🗺️ Roadmap\n\n- [ ] Web management UI (live sessions, replay, user management)\n- [ ] Database backend (PostgreSQL\u002FSQLite for config & logs)\n- [ ] Multi-factor authentication (TOTP\u002FWebAuthn)\n- [x] Command blacklist\u002Fwhitelist filtering\n- [x] SCP\u002FSFTP file transfer auditing\n- [ ] Cluster mode with load balancing\n- [ ] Real-time alerting (Slack\u002Fwebhook on suspicious activity)\n- [x] Session sharing (multiple admins watching one session)\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! Please open an issue first to discuss what you'd like to change.\n\n---\n\n## 📄 License\n\nThis project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.\n\n---\n\n\u003Cdiv align=\"center\">\n\n**Built with 🦀 Rust for maximum performance and safety.**\n\n*SSH Guard Proxy — Because security shouldn't be an afterthought.*\n\n\u003C\u002Fdiv>\n","SSH Guard Proxy 是一个用 Rust 构建的高性能 SSH 代理网关，旨在为基础设施提供安全审计、访问控制和会话记录。它通过统一认证、基于用户的访问控制（ACL）、完整的会话审计日志和终端回放功能来增强安全性。项目利用了 Rust 和 Tokio 异步运行时的优势，确保了低延迟和高效率，并且无需对目标服务器进行任何修改即可部署。适用于需要加强 SSH 访问管理与监控的企业环境或开发运维团队，特别是在直接 SSH 登录生产服务器存在安全隐患的情况下。","2026-06-11 04:06:45","CREATED_QUERY"]