ADVANCED SSH — INTERACTIVE LAB

Advanced SSH Techniques

Hardening configs, tunneling architectures, proxy chains, jump hosts, multiplexing, and intrusion prevention — all hands-on in a simulated environment.

Lab Exercises
1
SSH Hardening — Locking Down sshd_config
INTERMEDIATE ✓ Done
Scenario: Your organisation just spun up a new Ubuntu server. The default sshd_config ships with root login enabled and password authentication allowed on port 22. You need to harden it before the server goes live.

The current config is shown below. Use the terminal to apply each hardening directive. After all three changes, click Apply & Diff to see the before/after.

# /etc/ssh/sshd_config (before hardening) Port 22 PermitRootLogin yes PasswordAuthentication yes X11Forwarding yes UsePAM yes PrintLastLog yes AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server

Type each hardening command below. Run them in order:

  • 1.Change the port from 22 to 2222
  • 2.Disable root login
  • 3.Disable password authentication
sshd_config editor
student@hexworth:~$ sudo cat /etc/ssh/sshd_config | grep -E "^Port|^PermitRoot|^Password" Port 22 PermitRootLogin yes PasswordAuthentication yes
student@hexworth:~$
Hint: use sudo sed -i to edit in place, or type the exact directive. For step 1: sudo sed -i 's/^Port 22/Port 2222/' /etc/ssh/sshd_config
WHY IT MATTERS

Changing the default port is security-by-obscurity, but it eliminates 95 % of automated SSH scanners. Disabling root login forces attackers to know a valid username first. Disabling password auth makes brute-force attacks impossible — only key holders can connect.

REMEMBER

Always run sudo sshd -t (test mode) before restarting the daemon. A syntax error in sshd_config will lock you out of the server completely.

2
Remote Port Forwarding — Expose a Local Dev Server
INTERMEDIATE ✓ Done
Scenario: You are developing a web app running on localhost:3000. Your manager is on a remote machine at jump.hexworth.io and wants to review it. You need to expose your local server through the jump host so they can hit http://jump.hexworth.io:9090.
[Your Laptop] ── SSH tunnel ── [jump.hexworth.io] | | localhost:3000 0.0.0.0:9090 (your dev server) (manager connects here) Traffic flow: Manager browser ─► jump.hexworth.io:9090 ─► SSH tunnel ─► your laptop:3000

Type the command that creates the reverse tunnel:

reverse tunnel
# Your dev server is already running: # http://localhost:3000 — verified OK student@hexworth:~$
student@hexworth:~$
Hint: -R remote_port:local_host:local_port
Full command: ssh -R 9090:localhost:3000 student@jump.hexworth.io
FLAG BREAKDOWN

-R 9090:localhost:3000 tells the remote host to listen on port 9090 and forward incoming connections back through the SSH tunnel to your localhost:3000. The format is always -R [remote_bind:]remote_port:local_host:local_port.

GatewayPorts NOTE

By default the remote port binds only to 127.0.0.1 on the jump host. To allow external connections, the remote sshd needs GatewayPorts yes (or clientspecified) in its sshd_config. Without that, the manager cannot reach port 9090 from outside the jump host itself.

3
Dynamic Port Forwarding — SOCKS5 Proxy via SSH
ADVANCED ✓ Done
Scenario: You need to browse internal resources on the 192.168.10.0/24 subnet through a remote server that has access. Instead of a static port forward per service, you will create a dynamic SOCKS5 proxy so all browser traffic routes through the SSH host.
[Your Browser] ──SOCKS5──127.0.0.1:1080──SSH── [relay.hexworth.io] ──LAN── [192.168.10.x] DNS resolves on the REMOTE side (no DNS leak to local ISP) All TCP traffic proxied — HTTP, HTTPS, any protocol

Step 1: Open the SOCKS proxy tunnel on local port 1080.

SOCKS proxy tunnel
student@hexworth:~$
student@hexworth:~$
Hint: -D port opens the SOCKS listener locally.
-N = no remote command (tunnel only). -f = go to background.
Full: ssh -D 1080 -N -f student@relay.hexworth.io

Step 2: Configure Firefox to use the proxy.

Firefox Settings ► Network Settings ► Manual proxy config SOCKS Host: 127.0.0.1 Port: 1080 SOCKS v5: selected Proxy DNS: checked ← critical for DNS leak prevention
SOCKS PROXY vs VPN

A SOCKS proxy routes application-layer TCP/UDP traffic on a per-app basis. A VPN creates a virtual network interface and routes all system traffic at the OS level. Use SOCKS when you only want one application (e.g. browser) to go through the tunnel. Use VPN when you need the entire machine's traffic routed remotely.

DNS LEAK AWARENESS

Without "Proxy DNS" checked, Firefox resolves DNS locally even though HTTP traffic goes through the tunnel. Your ISP sees every domain you visit. Always enable remote DNS resolution when privacy is the goal.

4
SSH Jump Hosts — ProxyJump & Bastion Architecture
ADVANCED ✓ Done
Scenario: Your internal servers (web-01, db-01) are not exposed to the internet. Only a bastion host (bastion.hexworth.io) is publicly reachable. You need to SSH directly to web-01 without manually logging into the bastion first.
Internet ──► bastion.hexworth.io ──► Private LAN | web-01 (10.0.0.5) db-01 (10.0.0.6) (no public IP) (no public IP) Without ProxyJump: ssh user@bastion → then ssh user@web-01 (two steps, two passwords) With ProxyJump: ssh -J bastion user@web-01 (one command, end-to-end encrypted)

Type the one-liner to reach web-01 via the bastion:

proxy jump
# Target: student@web-01 (10.0.0.5) — no public IP # Bastion: student@bastion.hexworth.io — public, reachable student@hexworth:~$
student@hexworth:~$
Hint: -J jumphost is the ProxyJump flag. Syntax:
ssh -J user@jumphost user@destination
Full: ssh -J student@bastion.hexworth.io student@10.0.0.5

To make this permanent, add it to ~/.ssh/config:

# ~/.ssh/config Host web-01 HostName 10.0.0.5 User student ProxyJump student@bastion.hexworth.io IdentityFile ~/.ssh/id_ed25519 Host bastion.hexworth.io User student IdentityFile ~/.ssh/id_ed25519 ForwardAgent yes
SECURITY POSTURE

Bastion hosts reduce your attack surface from N servers to 1. The bastion receives all scrutiny: intrusion detection, enhanced logging, MFA, and strict firewall rules. Internal servers only accept connections from the bastion's IP, so even if an internal server is vulnerable, it cannot be reached directly from the internet.

ForwardAgent CAUTION

ForwardAgent yes lets the bastion use your local SSH keys to hop further. Convenient — but if the bastion is compromised, an attacker can use your forwarded agent to authenticate as you on other hosts. Use ForwardAgent only on trusted bastions, or prefer ProxyJump (which does not expose your agent).

5
SSH Multiplexing — ControlMaster & Persistent Connections
ADVANCED ✓ Done
Scenario: Your deployment pipeline opens dozens of SSH connections to the same host in rapid succession (git push, ansible, rsync, etc.). Each connection takes ~1 second for the TLS handshake. Multiplexing lets all subsequent connections reuse a single master socket — connection time drops to milliseconds.

Add multiplexing directives to ~/.ssh/config:

ssh_config editor
# Open your SSH config and add ControlMaster directives student@hexworth:~$
student@hexworth:~$
Try these commands in order:
1. ssh -O check deploy.hexworth.io — check master socket status
2. ssh -O exit deploy.hexworth.io — cleanly close master
3. grep ControlMaster ~/.ssh/config — verify config

The complete ~/.ssh/config block for multiplexing:

# ~/.ssh/config — multiplexing configuration Host deploy.hexworth.io ControlMaster auto ControlPath ~/.ssh/sockets/%r@%h:%p ControlPersist 10m ServerAliveInterval 60 ServerAliveCountMax 3 # Also create the socket directory: # mkdir -p ~/.ssh/sockets && chmod 700 ~/.ssh/sockets

Simulated benchmark — first connection vs multiplexed:

ControlMaster MODES

auto — use existing master if available, otherwise become the master.
yes — always become the master (fails if already exists).
no — never multiplex (always fresh connection).
autoask — ask before reusing (useful in interactive sessions).

WHEN TO USE IT

Multiplexing is ideal for: CI/CD pipelines, Ansible/Salt deployments, repeated git operations over SSH, and interactive sessions where you open many panes to the same server. ControlPersist 10m keeps the master alive 10 minutes after the last session closes, so rapid reconnects are still fast.

6
Fail2Ban — Brute-Force SSH Protection
EXPERT ✓ Done
Scenario: Your auth log is getting hammered — thousands of login attempts per hour from multiple IPs. You need to deploy Fail2Ban to automatically block IPs after repeated failures, effectively neutralising credential-stuffing and password-spray attacks.

Install fail2ban and check its status:

fail2ban lab
# auth.log is recording 2,847 failed SSH attempts in the last hour. # Your server is under active brute-force attack. student@hexworth:~$
student@hexworth:~$
Commands to try in order:
1. sudo apt install fail2ban -y
2. sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
3. sudo fail2ban-client status sshd
4. simulate attack — trigger the brute-force simulation
5. sudo fail2ban-client status sshd — check bans

Your /etc/fail2ban/jail.local SSH section:

# /etc/fail2ban/jail.local — SSH jail [sshd] enabled = true port = 2222 ; match your custom port filter = sshd logpath = /var/log/auth.log maxretry = 5 ; ban after 5 failures findtime = 600 ; ...within 10 minutes bantime = 3600 ; ban for 1 hour (use -1 for permanent) banaction = iptables-multiport ignoreip = 127.0.0.1/8 10.0.0.0/8 ; never ban these
HOW FAIL2BAN WORKS

Fail2Ban tails log files (auth.log, syslog) and matches lines against regex filters. When an IP hits maxretry failures within findtime seconds, fail2ban inserts an iptables/nftables DROP rule for that IP for bantime seconds. No credentials are ever exposed — the attacker's packets are silently dropped at the kernel level.

TUNING TIPS

Set bantime = -1 for permanent bans (recidive jail). Add your admin IPs to ignoreip or you risk locking yourself out if you mistype your password. For cloud servers, combine fail2ban with cloud-level security groups to block at the network edge before traffic even reaches the OS.

Lab Complete

0 / 6 exercises

Complete all six exercises to unlock lab completion credit.

Lab marked complete. Excellent work securing the stack.