SSH Explained: Mechanism, Public-Key Auth, and Commands thumbnail

SSH Explained: Mechanism, Public-Key Auth, and Commands

⏱ approx. 10 min views 68 likes 0 LOG_DATE:2026-05-09
TOC

What SSH is #

SSH (Secure Shell) is the protocol used to reach another computer over a network safely — for remote operation and file transfer. By encrypting the traffic, it sweeps away the three problems cleartext protocols like Telnet and rlogin had: eavesdropping, tampering, and impersonation. It runs on TCP port 22 by default, and is standardized in RFC 4253.

SSH is fundamental infrastructure for modern development: server operations, Git push, CI/CD deployments. OpenSSH (the OpenBSD-derived OSS implementation) ships with virtually every Linux distribution, macOS, and Windows 10 or later, and is now the de-facto standard.

Overview of SSH — client and server linked through an encrypted channel

The three steps of an SSH connection #

An SSH session is built in this order. Once you have these three steps in your head, the rest of the mechanism falls into place.

  1. Host authentication — the client asks "is the other side really the right server?"
  2. User authentication — the server asks "is the other side really the right user?"
  3. Encrypted communication — every byte from here on is encrypted with a shared key both sides derived independently.

1. Host authentication #

The server signs a challenge with its host key, and the client saves the resulting fingerprint into ~/.ssh/known_hosts. From the second connection onwards, anything that doesn't match the saved fingerprint triggers a warning — that is, the client can detect a man-in-the-middle. This is called the TOFU (Trust On First Use) model.

The authenticity of host 'example.com' can't be established.
ED25519 key fingerprint is SHA256:abcd1234...
Are you sure you want to continue connecting (yes/no/[fingerprint])?

There is still a window for a MITM on the very first connection, so in stricter setups the server operator publishes the fingerprint through a separate channel (internal wiki, HTTPS page) so users can verify it up front.

2. User authentication #

The two main methods:

Method How it works Recommendation
Password The username and password are sent over the already-encrypted channel △ — magnet for brute-force attacks
Public key The client signs with a private key, the server verifies with the public key ◎ — the standard in production

The usual production stance is to disable password authentication entirely and allow public-key auth only.

3. Encrypted communication #

After user authentication, both sides derive a shared key independently using Diffie–Hellman key exchange and use it with a symmetric cipher such as ChaCha20-Poly1305 or AES-GCM to encrypt all subsequent traffic. A passive eavesdropper cannot recover the key, so the payload is unrecoverable (forward secrecy).

How public-key authentication works #

In public-key auth, the client generates a pair of keys.

  • Private keynever leaves the client.
  • Public key — copied to the server ahead of time.

Public / private key pair — the public key sits on the server, the private key signs

Generating a key pair #

ssh-keygen -t ed25519 -C "your@email"

This produces ~/.ssh/id_ed25519 (private) and ~/.ssh/id_ed25519.pub (public). Ed25519 is short, strong, and fast to generate and verify. Pick it by default unless you have a specific compatibility constraint.

Always protect the private key with a passphrase — that way even if the file is stolen, the attacker still can't use it. Pair it with ssh-agent and you only have to enter the passphrase once per login session.

Registering the public key on the server #

ssh-copy-id user@example.com

This appends the public key to the server's ~/.ssh/authorized_keys and sets the right permissions (600).

The authentication flow (challenge / response) #

  1. The client says "I want to log in with this public key".
  2. The server sends a random challenge.
  3. The client signs the challenge with the private key and returns the signature.
  4. The server verifies the signature with the public key — if it matches, the user is in.

The private key itself never travels across the network. That's the key idea, and it also makes the flow resistant to replay attacks.

Core commands #

# connect
ssh user@example.com
ssh -p 2222 user@example.com           # specific port
ssh -i ~/.ssh/special_key user@host    # specific key file
ssh user@host 'uptime'                 # run a one-off command
ssh -vvv user@host                     # verbose log (troubleshooting)

# key management
ssh-keygen -t ed25519                  # new key
ssh-keygen -p -f ~/.ssh/id_ed25519     # change passphrase
ssh-keygen -l -f ~/.ssh/id_ed25519.pub # show fingerprint
ssh-keygen -R example.com              # remove an entry from known_hosts (key rotation)

File transfer #

Three file-transfer tools ride on the SSH encrypted channel. Pick whichever fits the task.

# scp — one-shot copy
scp local.txt user@host:/path/
scp -r local-dir/ user@host:/path/

# sftp — interactive file ops
sftp user@host
sftp> get remote.txt
sftp> put local.txt

# rsync over SSH — delta transfer (great for large file sets and backups)
rsync -avz -e ssh src/ user@host:/dst/

Port forwarding (tunneling) #

Port forwarding piggybacks another app's traffic on the SSH encrypted channel. There are three patterns:

Pattern Flag Typical use
Local forward -L Reach a remote database behind a bastion straight from your laptop
Remote forward -R Temporarily expose a local app to the outside (ngrok-style)
Dynamic -D SOCKS proxy — push browser traffic out through the SSH endpoint

Example: connect to a remote PostgreSQL through a bastion with plain psql.

ssh -L 5432:localhost:5432 user@bastion.example.com
# In another terminal
psql -h localhost

Bastion hopping (ProxyJump) #

When you have to hop through several bastions, chain them with -J. It replaces the older ProxyCommand.

ssh -J user@bastion user@internal-server
ssh -J user@b1,user@b2 user@target      # multi-hop

Minimum server-side settings (sshd_config) #

In /etc/ssh/sshd_config, these three lines are the absolute minimum to set.

PermitRootLogin no            # forbid direct root login
PasswordAuthentication no     # disable passwords (public keys only)
PubkeyAuthentication yes      # enable public-key authentication

After editing, run sshd -t to validate the syntax, then systemctl reload sshd to apply. Do not close your current session — test the change from a second terminal first, and only close the original session once the new one works. That's the safety net that keeps you from locking yourself out.

Handy client-side config (~/.ssh/config) #

Give each destination a short alias and ssh internal is all you need.

Host bastion
    HostName bastion.example.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_admin

Host internal
    HostName 10.0.0.5
    User deploy
    IdentityFile ~/.ssh/id_ed25519_deploy
    ProxyJump bastion

References #