Frontend Labs
⋯

Part 8 — SSH

SSH secures remote administration, file transfer, Git, tunnels, and service-to-service access. It reuses everything from Parts 3–5 — AEAD, ECDHE, signatures — with a different trust model from the web's PKI, and its own set of sharp edges.

Chapter 33 — What SSH is, and the connection protocol

In one sentence

SSH is an encrypted, authenticated channel between two machines, built as three stacked protocols — transport, user authentication, and multiplexed connection — running over one TCP connection (default port 22).

The problem it replaced

   Before SSH (mid-1990s): telnet, rlogin, rsh, rcp, ftp.

   telnet admin@server  ->  username and password sent in PLAINTEXT
   across the network. Every hop sees your root password. Session
   contents visible and injectable.

   SSH (1995, then the open OpenSSH in 1999) = "secure shell": the same
   remote-login workflow, inside strong crypto.

The three layers

   +--------------------------------------------------------------+
   |  CONNECTION protocol  (RFC 4254)                              |
   |    multiplexes the single encrypted pipe into CHANNELS:       |
   |    interactive shell, exec, port-forwards (-L/-R/-D),         |
   |    X11, SFTP subsystem, agent-forwarding. Many at once.       |
   +--------------------------------------------------------------+
   |  USER AUTHENTICATION protocol  (RFC 4252)                     |
   |    proves WHO the client is: publickey, password,             |
   |    keyboard-interactive (2FA), hostbased, GSSAPI.             |
   +--------------------------------------------------------------+
   |  TRANSPORT protocol  (RFC 4253)                               |
   |    key exchange (ECDHE / PQ), SERVER authentication via its   |
   |    host key, then AEAD-encrypted, integrity-protected records.|
   |    Also: algorithm negotiation, rekeying.                     |
   +--------------------------------------------------------------+
                          over  TCP :22

Order matters: the transport layer builds the secure channel and authenticates the server first; only then does the client authenticate the user inside that channel. Your password or key proof is never sent in the clear.

The transport handshake

   CLIENT                                            SERVER
   ------                                            ------
   ---- TCP connect :22 ------------------------->
   <--- "SSH-2.0-OpenSSH_10.2" banner ------------>   (both send version strings)
   ---- KEXINIT: my kex / cipher / MAC / hostkey lists -->
   <--- KEXINIT: server's lists ------------------>   (each picks the first
                                                      mutually-supported option)

   ---- key exchange (default: mlkem768x25519-sha256 on OpenSSH 10,
        or sntrup761x25519 on 9.x; else curve25519-sha256) ------->
   <--- server's ephemeral KEX public value
        + SERVER HOST KEY (public)
        + SIGNATURE over the exchange hash with the host key ------

   *** both derive the shared secret -> keys. Channel now encrypted
       with chacha20-poly1305 or aes-256-gcm, integrity via the AEAD
       tag or an EtM HMAC. ***

   ---- (client verifies the host key against known_hosts -- Ch 34) --
   ---- USERAUTH begins, inside the encrypted channel --------------

Two things worth noting:

  • SSH used ephemeral DH for forward secrecy from the start — years before TLS made it mandatory.
  • SSH already ships post-quantum key exchange by default. OpenSSH 9.0 (2022) made sntrup761x25519 a default; OpenSSH 10.0 (2025) made hybrid mlkem768x25519-sha256 the top preference. If both ends are recent, your SSH is already HNDL-resistant (Chapter 23). Check with ssh -Q kex.

User authentication methods

   publickey            client signs a challenge with its private key;
                        server checks against authorized_keys / a CA.
                        THE ONLY METHOD YOU SHOULD RELY ON.

   password             sent encrypted (not plaintext like telnet), but
                        brute-forceable, phishable, reused. Disable it on
                        anything internet-facing.

   keyboard-interactive generic prompt/response -> used for TOTP/OATH 2FA,
                        PAM. Combine with publickey for MFA.

   hostbased            the client HOST vouches for the user. Niche (HPC).

   gssapi-with-mic      Kerberos. Common in enterprise/AD environments.

   MFA in OpenSSH:  AuthenticationMethods publickey,keyboard-interactive
                    -> requires BOTH, in order.

The channel multiplexing (why one SSH connection does so much)

   One TCP:22 connection, many logical channels:

     session   ->  your interactive shell  (or a single `ssh host cmd`)
     direct-tcpip   ->  ssh -L  local forward  (expose a remote service locally)
     forwarded-tcpip -> ssh -R  remote forward (expose a local service remotely)
     "dynamic" ->  ssh -D  SOCKS proxy (route arbitrary TCP through the host)
     x11       ->  forwarded GUI apps
     subsystem ->  sftp (file transfer over the same secure channel)
     auth-agent-> agent forwarding (Ch 34 -- convenient and risky)

   ControlMaster lets multiple `ssh` invocations to the same host SHARE
   one connection -> near-instant subsequent logins.

Practice (25 min)

# 1. See the version banners and negotiated algorithms
ssh -vv localhost exit 2>&1 | grep -E "remote software version|kex:|cipher:|mac:|Server host key"

# 2. What key exchange / ciphers does your client offer?
ssh -Q kex
ssh -Q cipher
ssh -Q key
ssh -G localhost | grep -iE "^kexalgorithms|^ciphers|^macs"

# 3. Is PQ key exchange in the default list?
ssh -Q kex | grep -E "mlkem|sntrup"     # yes on OpenSSH 9+/10+

# 4. Watch the channel protocol: open a shell, a port-forward, and sftp
#    over ONE connection using multiplexing
mkdir -p ~/.ssh/cm
cat >> ~/.ssh/config <<'EOF'

Host localtest
    HostName localhost
    ControlMaster auto
    ControlPath ~/.ssh/cm/%r@%h:%p
    ControlPersist 60
EOF
ssh localtest true            # opens the master
ssh -O check localtest        # "Master running"
ssh localtest hostname        # reuses it -- instant
ssh -O exit localtest         # close it

Common confusions

  • "SSH is just an encrypted terminal." It's a general secure-tunnel protocol. Shells, file transfer, TCP forwarding, SOCKS proxying, and Git transport all ride it.
  • "The password is sent in plaintext like telnet." No — it's inside the encrypted transport. It's still weak for other reasons (brute force, phishing, reuse).
  • "SSH needs a CA like HTTPS." It doesn't require one. It defaults to trust-on-first-use for host keys and authorized_keys for users. SSH CAs exist and are great at scale (Chapter 35) but are opt-in.
  • "Port 22 open = insecure." Exposure is a concern, but a key-only, MFA-enabled, modern OpenSSH on 22 is fine. Moving to a high port is obscurity, not security (though it cuts log noise).

Check yourself

  1. Name SSH's three sub-protocols and what each does.
  2. Which is authenticated first in an SSH connection — the server or the user?
  3. Which user-auth method should you rely on, and which should you disable on internet-facing hosts?
  4. How does SSH already address "harvest now, decrypt later"?
  5. What does ssh -D do, versus ssh -L?

(Answers: Appendix F.)

Further reading

  • Book: SSH Mastery (2nd ed.), Michael W. Lucas — short, practical, the standard recommendation.
  • RFCs: 4251 (architecture), 4253 (transport), 4252 (auth), 4254 (connection). Skim 4251 for the model.
  • Man pages: ssh(1), sshd_config(5), ssh_config(5), ssh-keygen(1) — you'll live in these.
  • Site: man.openbsd.org/ssh and the OpenSSH release notes (each release's security and default changes are worth reading).

Generated from real-life-guide.md · 8 Oct 2026 16:36