SSH, Illustrated
Watch SSH build a trusted encrypted transport, authenticate a user, then open channels for a shell, command, or forwarding.
Verify the server during key exchange
How does the client know that sshd is the server it intended to reach?
TCP: client connects to server.example:22
$ ssh-keygen -F server.example # locate an existing known_hosts entry
During key exchange, the server signs the exchange with its host private key. The client checks the proof and the presented host key against its known_hosts policy before accepting the server identity.
Boundary: Host-key algorithms and verification policy depend on OpenSSH configuration. Host certificates and DNS-based mechanisms are additional supported models.
Failure state: The presented key differs from the trusted record. SSH warns because a changed host key can be legitimate, but it can also indicate a redirection or interception attempt.
Key agreement produces an encrypted transport
Why does SSH not encrypt the whole session with a user public/private key pair?
Exchange: public key-agreement values cross the network
$ ssh -vv alice@server.example … kex: algorithm: curve25519-sha256
Key exchange derives shared secret material. After NEWKEYS, both peers use symmetric session keys for normal traffic; asymmetric signatures prove identities without sending private keys.
Boundary: The view intentionally omits cryptographic calculations and algorithm details. Negotiated algorithms must be supported by both peers and accepted by local policy.
Failure state: No mutually acceptable key-exchange or host-key algorithm exists. The transport stops before user authentication.
The user proves access after encryption exists
Why does the private key stay on the client?
The encrypted transport already exists here. The user’s private key remains on the client or its local signing helper.
Offer: client offers public key identity
$ ssh-add -l 256 SHA256:… alice@laptop (ED25519)
For public-key authentication, the client offers a key and signs the authentication request locally, often through ssh-agent. The server checks the public key against its authorization source and verifies the signature.
Boundary: Public-key authentication is one method. Servers can also use passwords, certificates, keyboard-interactive methods, or policy modules.
Failure state: The encrypted transport remains valid, but user authentication fails because the key is absent, unauthorized, or does not satisfy server policy.
One SSH transport can carry several logical channels
What changes when you run a command, use SFTP, or create a tunnel?
localhost:15432 → SSH → bastion → db.internal:5432Forwarding opens a separate path from the server side to its destination. Login permission does not automatically grant forwarding permission.
Shell: interactive session channel
$ ssh -L 15432:db.internal:5432 alice@bastion # local listener carried through SSH
After authentication, SSH opens logical channels within the protected connection. A shell, remote command, SFTP subsystem, and forwarding each use a channel request with their own purpose.
Boundary: Forwarding permission can be restricted separately from login. ProxyJump uses SSH connections to reach a later host; it is not a magical network tunnel.
Failure state: The user may authenticate successfully while forwarding is refused by server policy or an unavailable destination behind the server.
Forwarding changes where a listener lives
What is different about -L, -R, and -D?
Local -L: client listener → SSH → server-side destination
Examples: ssh -L 15432:db.internal:5432 bastion / ssh -R 8080:localhost:3000 server / ssh -D 1080 bastion
Local forwarding opens a listener near the client and connects from the server side to one destination. Remote forwarding opens a listener near the server and returns traffic to the client side. Dynamic forwarding opens a local SOCKS listener for varying destinations.
Boundary: Listener binding, target reachability, and server forwarding policy affect each form. ProxyJump uses a bastion as a route to a second SSH server, not necessarily the final shell host.
Failure state: Authentication can succeed while the server rejects a forwarding request or cannot reach the destination.
Helpers change key handling, not the transport order
Where does ssh-agent sign, and what does forwarding it expose?
Local key: private material stays client-side
Illustrative: ssh-add -l / ssh -A bastion / TrustedUserCAKeys
ssh-agent is a local signing helper. Agent forwarding exposes a proxy socket to a remote host so it can request signatures; the private key is not copied, but a compromised remote session could misuse that signing ability. SSH certificates let a CA sign user or host identities.
Boundary: Hardware-backed keys and certificate policy vary by deployment. ControlMaster can reuse a connection but does not replace host verification or user authentication of the original master.
Failure state: A compromised remote environment with forwarded-agent access may request signatures while that connection is available.
Hardening choices affect different SSH stages
Which setting blocks TCP entry, user login, or a forwarding channel?
PermitRootLogin noPasswordAuthentication noAllowTcpForwarding noEach setting changes a different gate. Test the effective configuration and a working access path before changing a remote server.
Network: limit which clients can reach TCP :22
Examples: PermitRootLogin no / PasswordAuthentication no / AllowTcpForwarding no
A network firewall controls reachability before SSH starts. sshd authentication settings govern user access after transport setup. Forwarding settings govern channel requests after login. Treat these as distinct gates when changing policy.
Boundary: PasswordAuthentication no does not by itself describe all keyboard-interactive methods. Validate effective sshd configuration and retain a known working access path before tightening a remote host.
Failure state: The encrypted transport can remain healthy while server login policy refuses this user.
SSH failures tell you which stage stopped
Why does “permission denied” require a different investigation from “connection timed out”?
ssh -vvv alice@server.exampleTimeout before SSH version exchange → inspect DNS/TCP. Changed host key → inspect server identity. Permission denied after NEWKEYS → inspect user authorization.
Name/TCP: resolve and connect to port 22
Illustrative debug: ssh -vvv alice@server.example
Work from DNS and TCP to algorithm negotiation, host verification, user authentication, and channel setup. The first failed stage narrows the evidence you need; -v/-vv/-vvv logs can expose protocol progress without revealing private key material.
Boundary: Client diagnostics are only one side of the story. Server logs and effective sshd configuration may be needed for policy, account, or forwarding failures.
Failure state: The TCP connection and algorithm negotiation succeeded, but the client stopped at server host-key verification.