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
sntrup761x25519a default; OpenSSH 10.0 (2025) made hybridmlkem768x25519-sha256the top preference. If both ends are recent, your SSH is already HNDL-resistant (Chapter 23). Check withssh -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_keysfor 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
- Name SSH's three sub-protocols and what each does.
- Which is authenticated first in an SSH connection — the server or the user?
- Which user-auth method should you rely on, and which should you disable on internet-facing hosts?
- How does SSH already address "harvest now, decrypt later"?
- What does
ssh -Ddo, versusssh -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/sshand the OpenSSH release notes (each release's security and default changes are worth reading).