Skip to content

mac119/ssh_proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚         ╔═══╗                   β”‚
    β”‚         β•‘ ⬑ β•‘  SSH GUARD        β”‚
    β”‚         β•šβ•β•β•β•                   β”‚
    β”‚    β”Œβ”€β”€β”€β”       β”Œβ”€β”€β”€β”  β”Œβ”€β”€β”€β”    β”‚
    β”‚    β”‚ U β”œβ”€β”€β†’ P ── T β”‚  β”‚ T β”‚    β”‚
    β”‚    β””β”€β”€β”€β”˜  ↕    β””β”€β”€β”€β”˜  β””β”€β”€β”€β”˜    β”‚
    β”‚         AUDIT                   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ›‘οΈ SSH Guard Proxy

A high-performance SSH proxy gateway built in Rust for security auditing, access control, and session recording.

Rust License: MIT tokio

Every keystroke recorded. Every connection authorized. Every session auditable.


🎯 Why SSH Guard Proxy?

In 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.

The Problem

  • Developers SSH directly into production servers with no oversight
  • No centralized record of who did what and when
  • Shared credentials make accountability impossible
  • Revoking access requires touching every server

The Solution

Developer β†’ SSH Guard Proxy β†’ Target Server
                ↓
          Audit Log (every keystroke)

✨ Features

Feature Description
πŸ” Unified Authentication Password (Argon2id) and public key auth at the gateway
πŸŽ›οΈ Access Control (ACL) Per-user host access policies β€” who can access what
πŸ“ Full Audit Logging Every input/output recorded in JSON Lines format
🎬 Session Recording Asciicast v2 format β€” replay any session with asciinema
⚑ High Performance Built on Rust + Tokio async runtime β€” minimal overhead
πŸ—οΈ Zero Target Changes No agent or modification needed on target servers
πŸ”‘ Host Key Auto-generation Ed25519 host keys generated on first run
🚦 Connection Limiting Max session control and auth failure lockout

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      SSH Guard Proxy                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                   β”‚
β”‚   User ──SSH──→ [SSH Server] ──→ [Auth & ACL] ──→ [Session Mgr]  β”‚
β”‚                                                        β”‚          β”‚
β”‚                                                        β–Ό          β”‚
β”‚                  [Audit Logger] ◀────────────── [SSH Client] ──→ Target
β”‚                       β”‚                                           β”‚
β”‚                       β–Ό                                           β”‚
β”‚                 logs/audit.jsonl                                   β”‚
β”‚                                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Flow

  1. User connects: ssh admin@proxy -p 2222
  2. Proxy authenticates the user (password or public key)
  3. User selects a target host from the authorized list
  4. Proxy establishes SSH connection to target
  5. All data is bidirectionally forwarded and logged
  6. Session ends β†’ audit record finalized

πŸš€ Quick Start

Prerequisites

  • Rust 1.70+ (install via rustup)
  • Target servers accessible via SSH from the proxy host

Build

git clone https://github.com/mac119/ssh_proxy.git
cd ssh_proxy
cargo build --release

Configure

1. Proxy Settings (config/proxy.toml)

[server]
listen_address = "0.0.0.0"
listen_port = 2222
host_key_path = "config/host_key"

[session]
idle_timeout_secs = 1800
max_sessions = 100

[audit]
log_dir = "logs"
record_session = true

[security]
max_auth_attempts = 3
lockout_duration_secs = 300

2. Add Users (config/users.toml)

Generate a password hash first:

cargo run --bin hash_password -- 'YourSecurePassword'
# Output: $argon2id$v=19$m=19456,t=2,p=1$...

Then add to config:

[[users]]
name = "admin"
password_hash = "$argon2id$v=19$m=19456,t=2,p=1$..."
public_keys = []
allowed_hosts = ["*"]  # Access to all hosts

[[users]]
name = "developer"
password_hash = "$argon2id$v=19$m=19456,t=2,p=1$..."
public_keys = ["ssh-ed25519 AAAAC3Nza..."]
allowed_hosts = ["web-01", "web-02"]  # Restricted access

3. Add Target Hosts (config/hosts.toml)

[[hosts]]
name = "web-01"
address = "192.168.1.10"
port = 22
username = "deploy"
auth_method = "key"
private_key_path = "config/keys/web-01"

[[hosts]]
name = "db-01"
address = "10.0.0.50"
port = 22
username = "dbadmin"
auth_method = "password"
password = "encrypted:your_password_here"

Run

# Development
cargo run

# Production
./target/release/ssh_proxy

Connect

ssh admin@your-proxy-host -p 2222

You'll see:

Welcome, admin! Available hosts:
─────────────────────────────────────
  [1] web-01 (192.168.1.10:22)
  [2] web-02 (192.168.1.11:22)
  [3] db-01 (10.0.0.50:22)
─────────────────────────────────────
Select host number: 

Select a host and you're in β€” fully transparent, fully audited.


πŸ“Š Audit Logs

All audit data is stored in logs/audit.jsonl in append-only JSON Lines format.

Log Events

Event Description
auth_success Successful authentication
auth_failure Failed authentication attempt
session_start User connected to a target host
session_end Session terminated
data (input) User keystrokes / commands
data (output) Server responses

Example Log Entries

{"event":"auth_success","timestamp":"2026-05-05T07:10:00Z","user":"admin","peer_addr":"10.0.1.5:54321","method":"password"}
{"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"}
{"event":"data","timestamp":"2026-05-05T07:10:10Z","session_id":"a1b2c3d4","direction":"input","data_base64":"bHMgLWxhCg==","data_len":7}
{"event":"data","timestamp":"2026-05-05T07:10:10Z","session_id":"a1b2c3d4","direction":"output","data_base64":"dG90YWwgNDgK...","data_len":256}
{"event":"session_end","timestamp":"2026-05-05T07:45:00Z","session_id":"a1b2c3d4"}

Decoding Commands from Logs

# View all input commands from a session
grep '"direction":"input"' logs/audit.jsonl | \
  jq -r '.data_base64' | \
  while read line; do echo "$line" | base64 -d; done

# Find who connected today
grep '"event":"session_start"' logs/audit.jsonl | \
  grep "$(date +%Y-%m-%d)" | \
  jq '{user, target_host, timestamp}'

# Count failed logins
grep '"event":"auth_failure"' logs/audit.jsonl | wc -l

Session Replay

Sessions are recorded in asciicast v2 format:

# Replay a recorded session
asciinema play logs/sessions/<session_id>.cast

🏒 Production Deployment

Systemd Service

Create /etc/systemd/system/ssh-guard-proxy.service:

[Unit]
Description=SSH Guard Proxy
After=network.target

[Service]
Type=simple
User=sshproxy
Group=sshproxy
WorkingDirectory=/opt/ssh_proxy
ExecStart=/opt/ssh_proxy/ssh_proxy
Restart=always
RestartSec=5

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/ssh_proxy/logs

[Install]
WantedBy=multi-user.target
sudo systemctl enable ssh-guard-proxy
sudo systemctl start ssh-guard-proxy

File Permissions

chmod 600 config/host_key
chmod 600 config/keys/*
chmod 644 config/*.toml
chmod 700 logs/

Log Rotation

Add to /etc/logrotate.d/ssh-guard-proxy:

/opt/ssh_proxy/logs/audit.jsonl {
    daily
    rotate 90
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

Firewall

# Only expose the proxy port
ufw allow 2222/tcp
# Block direct SSH to target hosts from outside
ufw deny from any to 192.168.1.0/24 port 22

πŸ“ Project Structure

ssh_proxy/
β”œβ”€β”€ Cargo.toml                 # Dependencies & build config
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ proxy.toml             # Main proxy configuration
β”‚   β”œβ”€β”€ users.toml             # User accounts & ACL
β”‚   β”œβ”€β”€ hosts.toml             # Target host definitions
β”‚   └── host_key              # Auto-generated Ed25519 host key
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.rs               # Entry point
β”‚   β”œβ”€β”€ config.rs             # Configuration loading
β”‚   β”œβ”€β”€ server/
β”‚   β”‚   β”œβ”€β”€ mod.rs            # TCP listener & session spawning
β”‚   β”‚   └── handler.rs        # SSH protocol handler (auth, data relay)
β”‚   β”œβ”€β”€ client/
β”‚   β”‚   └── mod.rs            # SSH client (connects to targets)
β”‚   β”œβ”€β”€ auth/
β”‚   β”‚   β”œβ”€β”€ mod.rs            # Authentication (Argon2id, pubkey)
β”‚   β”‚   └── acl.rs            # Access control logic
β”‚   β”œβ”€β”€ session/
β”‚   β”‚   └── mod.rs            # Session lifecycle management
β”‚   └── audit/
β”‚       β”œβ”€β”€ mod.rs            # Audit event logger
β”‚       └── recorder.rs       # Asciicast session recorder
β”œβ”€β”€ src/bin/
β”‚   └── hash_password.rs      # CLI tool to generate password hashes
└── logs/                      # Audit output directory

πŸ”§ Technology Stack

Component Choice Rationale
Language Rust Memory safety, zero-cost abstractions, fearless concurrency
SSH Protocol russh Native async SSH implementation (server + client)
Async Runtime Tokio Industry-standard, battle-tested async runtime
Password Hashing Argon2id Winner of Password Hashing Competition
Logging tracing Structured, async-aware instrumentation
Config TOML + serde Human-readable, type-safe configuration

πŸ—ΊοΈ Roadmap

  • Web management UI (live sessions, replay, user management)
  • Database backend (PostgreSQL/SQLite for config & logs)
  • Multi-factor authentication (TOTP/WebAuthn)
  • Command blacklist/whitelist filtering
  • SCP/SFTP file transfer auditing
  • Cluster mode with load balancing
  • Real-time alerting (Slack/webhook on suspicious activity)
  • Session sharing (multiple admins watching one session)

🀝 Contributing

Contributions are welcome! Please open an issue first to discuss what you'd like to change.


πŸ“„ License

This project is licensed under the MIT License β€” see the LICENSE file for details.


Built with πŸ¦€ Rust for maximum performance and safety.

SSH Guard Proxy β€” Because security shouldn't be an afterthought.

About

πŸ›‘οΈ 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.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages