Skip to content

Cryptographic OpenSSH Architecture: Bastions, ProxyJump & Encrypted Port Forwarding

Created: 2026-11-08  ยท  Last updated: 2026-11-08  ยท  Nejat Hakan

Executive Summary: OpenSSH is the primary administrative gateway to every production Linux server. Relying on legacy RSA keys, unhardened default ciphers, or password authentication exposes critical infrastructure to automated brute-force attacks and credential theft. Professional systems engineering requires Edwards-curve Ed25519 key pairs, post-quantum hybrid key exchange, strict drop-in sshd_config hardening, connection multiplexing via ControlMaster, bastion jump hosts via ProxyJump, and encrypted port forwarding (Local, Remote, and Dynamic SOCKS5).

  • Ed25519 & Cryptography


    Generate modern Ed25519 keys with high KDF iteration rounds (-a 100), configure post-quantum KEX, and eliminate obsolete RSA/DSA keys.

  • Production sshd Hardening


    Enforce zero-password policies, drop root login, restrict ciphers to ChaCha20-Poly1305 and AES-GCM, and configure rate limits.

  • Bastions & ProxyJump


    Traverse isolated DMZ and LAN network zones securely using ProxyJump (-J), avoiding the security hazards of legacy agent forwarding (-A).

  • Port Forwarding (-L, -R, -D)


    Tunnel local database clients to remote loopback daemons (-L), expose internal testing servers (-R), and spawn dynamic SOCKS5 proxies (-D).


1. Cryptographic Key Management: The Death of RSA

Legacy RSA-2048 and RSA-4096 keys suffer from slow key generation, susceptibility to timing attacks, and large mathematical key sizes. Modern Linux infrastructure standardizes on Ed25519 (Edwards-curve Digital Signature Algorithm over Curve25519):

  • Deterministic Signatures: Eliminates the risk of catastrophic private key leakage caused by faulty random number generators.
  • Compact Footprint: Public keys are only 68 characters long, making auditing in authorized_keys trivial.
  • Resilient Key Derivation Function (KDF): Uses bcrypt PBKDF to protect private keys against brute-force password cracking on stolen laptops.

Generating Hardened Ed25519 Keypairs

Generate an Ed25519 key with 100 bcrypt KDF rounds and a descriptive comment:

# Generate Ed25519 keypair with high KDF iteration rounds
ssh-keygen -t ed25519 -a 100 -C "nejat@infra-workstation" -f ~/.ssh/id_ed25519_infra

# Set strict filesystem permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519_infra
chmod 644 ~/.ssh/id_ed25519_infra.pub

Copy the public key securely to your target Debian server:

ssh-copy-id -i ~/.ssh/id_ed25519_infra.pub nejat@192.168.1.50

2. Production Server Hardening (sshd_config.d)

In Debian 11/12+, never edit the monolithic /etc/ssh/sshd_config directly. Place hardened configurations into /etc/ssh/sshd_config.d/99-hardening.conf:

# File: /etc/ssh/sshd_config.d/99-hardening.conf
# 1. Authentication Restrictions
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey

# Only allow specific administrative system accounts
AllowUsers nejat

# 2. Hardened Cryptographic Algorithms
# Post-quantum hybrid KEX (sntrup761) + classical Curve25519
KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org

# Authenticated Encryption with Associated Data (AEAD) ciphers only
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com

# Encrypt-then-MAC (ETM) algorithms
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# 3. Connection Limits & Brute-Force Mitigation
MaxAuthTries 3
LoginGraceTime 20
MaxSessions 2
ClientAliveInterval 300
ClientAliveCountMax 2

# 4. Disable Unused Features
X11Forwarding no
AllowAgentForwarding no

Always test the configuration syntax before reloading the daemon to prevent lockouts:

# Validate syntax (returns nothing if valid)
sudo sshd -t

# Reload configuration without dropping existing active sessions
sudo systemctl reload ssh

3. Bastion Hosts & Multi-Hop Access: ProxyJump vs. Agent Forwarding

Accessing internal database clusters or private hypervisors in isolated subnets requires passing through a Bastion Host (Jump Server) in the DMZ:

%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
    WORK["๐Ÿ’ป Workstation<br/>Private Key stored locally"]
    BAST["๐Ÿฐ Bastion Host (DMZ)<br/>203.0.113.10:22<br/>(Public WAN IP)"]
    INT["๐Ÿ—„๏ธ Internal Database Server<br/>10.10.20.11:22<br/>(Private Subnet - No Internet)"]

    WORK ==>|"1. SSH ProxyJump (-J bastion)<br/>End-to-End Encrypted Tunnel"| BAST
    BAST ==>|"2. Raw TCP Forwarding via nc/stdio"| INT

The Fatal Hazard of Legacy Agent Forwarding (ssh -A)

Legacy tutorials frequently recommend forwarding your SSH agent (ssh -A bastion). Never do this in production. If an attacker compromises the bastion host, they can access your forwarded Unix domain socket ($SSH_AUTH_SOCK) to impersonate you and authenticate to any server your key allows!

The Modern Solution: ProxyJump (-J)

ProxyJump establishes an end-to-end encrypted channel directly between your workstation and the target internal host. The bastion acts strictly as a raw TCP proxy (stdio forwarder) and never sees your decrypted traffic, private keys, or agent socket.

# Ad-hoc CLI jump connection
ssh -J nejat@203.0.113.10 nejat@10.10.20.11

4. Workstation Automation: Client ~/.ssh/config

Configure persistent multiplexing, keepalives, and jump hosts in ~/.ssh/config:

# File: ~/.ssh/config

# Global Settings for all connections
Host *
    # Connection Multiplexing (Instant subsequent shells without re-authenticating)
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m

    # Keepalives to prevent stateful NAT dropouts on idle sessions
    ServerAliveInterval 30
    ServerAliveCountMax 3

    # Security: Strict host key checking & identity isolation
    StrictHostKeyChecking ask
    IdentitiesOnly yes

# 1. Bastion Host in DMZ
Host bastion
    HostName 203.0.113.10
    User nejat
    Port 22
    IdentityFile ~/.ssh/id_ed25519_infra

# 2. Internal Database Cluster (Auto-routed through Bastion)
Host db-primary
    HostName 10.10.20.11
    User nejat
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519_infra
    # Automatically tunnel local port 15432 to remote localhost:5432
    LocalForward 127.0.0.1:15432 127.0.0.1:5432

Now you can connect to the internal database server with a single command:

ssh db-primary

5. The Three Port Forwarding Modes: Local, Remote & Dynamic

%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
    subgraph L["Local Forwarding (-L)"]
        L_SRC["Local 127.0.0.1:15432"] -->|"Encrypted SSH"| L_DST["Remote DB 127.0.0.1:5432"]
    end
    subgraph R["Remote Forwarding (-R)"]
        R_SRC["Remote Server :8080"] -->|"Encrypted SSH"| R_DST["Local Dev :3000"]
    end
    subgraph D["Dynamic Forwarding (-D)"]
        D_SRC["Browser SOCKS5 :1080"] -->|"Encrypted SSH"| D_DST["Internet via Remote Host"]
    end

1. Local Port Forwarding (-L)

Binds a port on your local machine and tunnels all traffic sent to it to a specified host and port reachable from the remote server:

# Syntax: ssh -L [bind_address:]local_port:target_host:target_port server
# Connect your local DBeaver/psql client to remote internal PostgreSQL
ssh -N -L 127.0.0.1:15432:127.0.0.1:5432 nejat@db-primary

Connect locally: psql -h 127.0.0.1 -p 15432 -U postgres

2. Remote Port Forwarding (-R)

Binds a port on the remote server and forwards incoming traffic back to a port on your local machine. Ideal for exposing a local webhook receiver or development server to team members:

# Syntax: ssh -R [bind_address:]remote_port:target_host:local_port server
# Expose your local web app running on :3000 to port :8080 on the remote server
ssh -N -R 127.0.0.1:8080:127.0.0.1:3000 nejat@bastion

3. Dynamic SOCKS5 Proxy (-D)

Turns your SSH connection into an encrypted SOCKS5 proxy. Point your web browser or curl to 127.0.0.1:1080 to route all web traffic through the remote server:

# Spawn local SOCKS5 proxy on port 1080
ssh -N -D 127.0.0.1:1080 nejat@bastion

# Route curl requests through the remote server
curl --socks5-hostname 127.0.0.1:1080 https://icanhazip.com

(The -N flag instructs OpenSSH not to execute a remote shell, keeping the session dedicated strictly to port forwarding).


6. Next Steps

With cryptographic remote access and encrypted port forwarding secured, proceed to establishing stateful network firewalls in the Linux kernel:

  • Stateful Packet Filtering with nftables & ufw


    Master Netfilter kernel hooks, dual-stack inet tables, connection tracking (conntrack), and UFW profile management.

    nftables & UFW Guide