SSD Nodes Learn 🎉 VPS from $4.99/mo
Guides Matt ConnorBy Matt Connor

What is SSH, and how does it work?

SSH is an encrypted channel to a remote server. Learn the client and server model, port 22, host key fingerprints, and key versus password login.

What is SSH?

SSH (secure shell) is a protocol for logging in to a computer somewhere else and running commands on it through an encrypted connection. What you type goes to the remote machine, its output comes back, and nobody watching the network in between can read either one. A rented Linux server has no screen and no keyboard attached to it, so SSH is how the machine gets used at all.

The name covers two things. SSH is the protocol, described in RFC 4251 through RFC 4254. OpenSSH is the program that implements it, and it is what almost every Linux server and almost every laptop actually runs. When someone says "SSH into the server", they mean the client program ssh on their machine talking to the server program sshd on the other end.

The problem SSH was built to replace

Remote login is much older than SSH. Telnet opened a plain TCP connection to port 23 and sent every byte exactly as it was typed. Nothing was encrypted, and that included your password. Anyone who could see the traffic could read it: a person on the same office network, or an operator of any router along the path. The rlogin family had the same weakness, and it trusted the client machine by name, which means trusting whatever the network claimed that name to be.

Tatu Ylönen wrote the first SSH in 1995 at Helsinki University of Technology, after a password sniffing attack on the university network. The design keeps the useful part of telnet, a byte stream between your terminal and a remote shell, and adds the two things telnet has no answer for: encryption of the stream, and proof that the server on the other end is the one you meant to reach.

That second part is easy to overlook, and it is half of what SSH is. Encryption on its own would not save you. A machine in the middle could accept your connection, encrypt it perfectly, read everything you send, and pass it along to the real server. SSH blocks that by giving every server a permanent identity, called the host key, and checking it on every single connection.

How the client and server model works

There are two programs. On the server, sshd runs all the time and waits for connections. On your machine, ssh makes them. They are separate programs with separate configuration files, and confusing the two is the most common reason an edit has no effect.

  • The server reads /etc/ssh/sshd_config. This is where password login is turned off and where the listening port is set.
  • The client reads /etc/ssh/ssh_config for system defaults, then ~/.ssh/config for your own per host settings.

On Debian and Ubuntu the service unit is called ssh. On RHEL, Rocky and Fedora it is called sshd. Recent Ubuntu releases install it socket activated, so systemctl status ssh can report inactive (dead) while the machine is perfectly reachable, because ssh.socket is the unit doing the listening and it starts the service on demand.

The client does not have to be OpenSSH. PuTTY on Windows, Termius on a phone, and the remote support built into editors all speak the same protocol to the same sshd. Windows 10 and 11 also include the OpenSSH client, so ssh you@server works in PowerShell with nothing to install.

Why does SSH use port 22?

A port is a number that tells the kernel which listening program an incoming connection belongs to, and ports on Linux work the same way for every service. SSH uses 22 because IANA assigned it in 1995. Ylönen asked for a free number sitting next to the protocols SSH was written to replace: 21 was FTP, 23 was telnet, and 22 was unused.

Because 22 is the default, everything assumes it. Your Git remote, your backup script and your provider's control panel all try 22 first. So does every automated scanner on the internet. A new server with password login enabled starts collecting lines like this in /var/log/auth.log within minutes of booting:

Failed password for invalid user admin from 203.0.113.55 port 43122 ssh2

That traffic is constant, and it is not aimed at you personally. Moving sshd to port 2222 removes most of those lines, because the scanners are sweeping the whole internet on 22 rather than studying your server. It does not make the machine harder to break into for anyone who actually looks at it. Treat a port change as noise reduction and nothing more.

You can watch the server answer before you log in at all:

nc 203.0.113.10 22

On Ubuntu 24.04 that prints something close to SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13. The banner is sent in cleartext, before any encryption exists, because both sides need it to agree on the protocol version. Press Ctrl+C to close the connection.

What happens on the wire when you connect

The sequence below is what one ssh you@server does before you see a prompt.

  1. The client resolves the hostname to an IP address, then opens a TCP connection to port 22.
  2. Both sides send their version banner in cleartext.
  3. Both sides send the lists of algorithms they support: key exchange, cipher, message authentication, compression. Still cleartext. The strongest option both sides know is the one chosen.
  4. Key exchange runs. Current OpenSSH prefers curve25519-sha256. Both ends end up holding the same shared secret without that secret ever crossing the network, so somebody who recorded the whole conversation cannot work it out afterwards.
  5. The server signs the result of that exchange with its host private key. Your client checks the signature against the host public key it has on file. This is the step that stops a machine in the middle from impersonating your server.
  6. Encryption starts. chacha20-poly1305@openssh.com is the default cipher in current OpenSSH.
  7. Only now does the client authenticate you, with a password or a key. Your username and password travel inside the encrypted channel.
  8. The client opens a channel and asks for a shell.

The order in that list is the entire difference from telnet. Authentication happens after the channel is encrypted and after the server has proved its identity, so there is no moment where your password sits on the wire in the open.

Someone watching the network still learns something. They see your IP address, the server's IP address, port 22, both cleartext version banners, and the timing and rough size of every packet. They do not see your username, your password, your commands or their output. The hostname lookup in step 1 is not part of SSH and is usually not private, so the DNS query that resolves your server name can reveal which machine you are about to reach even though the session itself stays sealed.

The host key, and that first connection fingerprint prompt

When openssh-server is installed, it generates host key pairs for the machine and writes them to /etc/ssh/, for example ssh_host_ed25519_key and ssh_host_ed25519_key.pub. The private half never leaves the server. The public half is the server's identity, and it is what the signature in step 5 is checked against.

The first time you connect to a new server, your client has nothing to compare against, so it asks you:

The authenticity of host '203.0.113.10 (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:E9nVQ5Sm2oQ3nGm5Zf1tOaU7Xh0k2p8bWc4dLrTvYxA.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

The fingerprint is a SHA256 hash of the host public key, printed in base64, so it is short enough to compare by eye. Typing yes writes that key into ~/.ssh/known_hosts on your own machine. Every later connection to the same address compares the key the server offers against the stored one. When they match, nothing is printed and you go straight to your prompt.

This model is called trust on first use, and it is worth being honest about what it costs. The first connection is the one moment you are unprotected, because you are accepting a key you have never seen before. To close that gap, get the fingerprint by another route and compare. Most providers print it in the boot output shown in their web console, and you can also print it on the server itself:

ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

That prints the same SHA256: string the prompt showed you. The [fingerprint] choice in the prompt exists for exactly this: paste the fingerprint you expect, and the client continues only if it matches what the server presented.

On Debian and Ubuntu, known_hosts is hashed by default, so the file holds lines that begin with |1| instead of readable hostnames. Run ssh-keygen -F 203.0.113.10 to find the entry for one host.

Why does SSH say the host key has changed?

Sooner or later you will meet this wall of text:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

It ends with Host key verification failed. and the client refuses to connect. It also prints Password authentication is disabled to avoid man-in-the-middle attacks., because typing your password into an unknown machine is the precise harm this check exists to prevent.

The message reads like an emergency, and most of the time it is not one. The ordinary causes:

  • You rebuilt or reinstalled the server, so sshd generated fresh host keys on first boot. This is by far the most common reason.
  • You destroyed one VPS and created another, and the provider handed the new machine the old IP address.
  • You are connecting through a forward or a load balancer that now reaches a different backend machine.
  • Something really is intercepting the connection.

Decide which one it is before you clear anything. If you reinstalled the machine ten minutes ago, the cause is obvious. If nothing changed on your side, stop and investigate, because this warning is the check doing its job. Once you are sure, drop the stale entry and reconnect:

ssh-keygen -R 203.0.113.10

The next connection shows the fingerprint prompt again, which gives you a fresh chance to compare it against the provider console.

Password login versus key login

Password authentication sends your password inside the already encrypted channel, and sshd checks it against the account database, normally through PAM (pluggable authentication modules). It needs no preparation, which is why a provider can hand you a new server with nothing but a root password.

The weakness is not the encryption. It is that a password is a short secret, you send it to the server on every login, and port 22 is guessed at around the clock by machines that never get bored.

Public key authentication works differently. You create a key pair on your own machine. The public half goes into ~/.ssh/authorized_keys inside your account on the server. The private half stays on your laptop and is never transmitted. To log in, the client signs a piece of data that includes the session identifier from the key exchange, and the server verifies that signature using the public key it already holds. Because the signed data is tied to this one session, a captured signature is worthless against anything else.

Watch the direction, because reversing it is common and it is harmful: the public key goes on the server, the private key stays with you. A private key copied onto a server is a private key you can no longer trust.

Key login has its own failure modes. sshd ignores keys when the file permissions are too loose, and it says so in the server log:

Authentication refused: bad ownership or modes for directory /home/ubuntu/.ssh

The client only ever tells you Permission denied (publickey), which is the same message for a dozen different causes, so reading the publickey error properly is worth learning before you are locked out. The practical work of creating keys, protecting them with a passphrase and loading them into an agent belongs in SSH key management, and switching password login off without stranding yourself belongs in hardening SSH on a VPS.

SFTP, scp and port forwarding ride the same connection

Here is the idea that makes the rest of the SSH world fall into place. Authentication opens an encrypted connection, and that connection can carry several independent channels at the same time. A shell is one kind of channel among several.

  • A remote shell. ssh you@server opens a session channel and asks for an interactive shell.
  • A single command. ssh you@server uptime opens a channel, runs one command, prints the output and exits.
  • SFTP. The client asks sshd to start its sftp subsystem, and file transfer runs inside the same connection. SFTP is a file transfer protocol that rides SSH, and it shares no design with FTP. The protocol that is FTP with encryption added is called FTPS, and it is unrelated.
  • scp. Copies files using the same login. Since OpenSSH 9.0, released in 2022, scp uses the SFTP protocol underneath by default.
  • Port forwarding. ssh -L 8080:localhost:80 you@server turns port 8080 on your laptop into a doorway to port 80 on the server, carried inside the encrypted connection. -R forwards in the other direction, and -D 1080 turns the session into a SOCKS proxy.
  • Git. A remote like git@github.com:user/repo.git is an SSH login whose remote side runs a command handler instead of a shell.
  • rsync and Ansible are SSH clients too. They open a channel, run something, and read the output back.

Every item on that list uses the same port, the same host key check and the same credentials. That is why setting up key authentication once repays the effort straight away: each of those tools inherits it. It is also why the same ~/.ssh/config file that shortens your logins is the file that scales when you are managing several Linux servers from one laptop.

What SSH does not do

  • It does not make your server secure. SSH protects the path to the door. The door is still there, and people will keep trying the handle. Blocking repeated login attempts with fail2ban handles the volume, and key only authentication removes the thing they are guessing.
  • It does not protect you from your own machine. Anyone with access to your laptop has your private key and your loaded agent.
  • It does not hide that you are using SSH. The port number and the cleartext version banner announce it.
  • It does not cover what happens before the connection exists. The name lookup, and your decision about which address to trust, both come first.

Where to go from here

If you have a new server open in a provider console right now, the useful order is fixed. Get in, create a normal user, install your key, then close the easy paths behind you. The first ten minutes on a new VPS walks that order start to finish, and what a VPS actually is fills in the machine underneath if the words are still new. After that, keys and hardening are the two posts to read, in that sequence.

FAQ

What does SSH stand for?

SSH stands for secure shell. It is a protocol for logging in to a remote computer and running commands on it over an encrypted connection, defined in RFC 4251 through RFC 4254. OpenSSH is the implementation nearly everyone uses: the ssh client on your machine, and the sshd server on the remote one. It replaced telnet, which sent everything including passwords across the network in plain text.

Why does SSH use port 22?

IANA assigned port 22 to SSH in 1995, next to FTP on 21 and telnet on 23, the protocols it was written to replace. Nothing forces that number: Port in /etc/ssh/sshd_config changes it on the server, and ssh -p picks a different one on the client. Because 22 is the default, automated scanners knock on it constantly, which is why a fresh server's /var/log/auth.log fills with Failed password for invalid user lines. Changing the port reduces that noise and adds no real protection.

What should I do when SSH warns that the host key has changed?

Find the cause before you clear anything. The usual reason is harmless: the server was rebuilt, so sshd generated new host keys, or a new machine was given the old IP address. If you know the machine was rebuilt, run ssh-keygen -R <host> to drop the stored key, reconnect, and compare the fingerprint you are shown with the one your provider console reports. If nothing changed on your side, do not connect and do not type your password. OpenSSH already refuses password authentication in this state for that exact reason.

Are SFTP and scp different from SSH?

They run on top of it. Once you have authenticated, the SSH connection can carry several channels, and a shell is only one of them. SFTP is a file transfer protocol that uses the sftp subsystem of sshd over that same connection, and scp has used the SFTP protocol underneath since OpenSSH 9.0. Port forwarding and Git over SSH are channels on the same connection too. All of them use the same port, the same host key check and the same login. Note that SFTP is not FTP with encryption added; that one is called FTPS and it is a separate protocol.

Is key authentication really better than a password?

Yes, for any server reachable from the internet. A password is a short secret that you hand to the server on every login, and port 22 is guessed at continuously by automated clients. With a key pair, the private half never leaves your machine: the client signs data tied to the current session, and the server checks that signature against the public key in ~/.ssh/authorized_keys. A recorded signature cannot be replayed against another server. Protect the private key with a passphrase, because a key file with no passphrase is a working login for anyone who copies it.