1. SSH keys that live on a security key (ed25519-sk)
Since OpenSSH 8.2 a key pair can be bound to a FIDO authenticator: ssh-keygen -t ed25519-sk creates it, and every login needs a touch. Nothing is installed on the server beyond a recent OpenSSH; the public key goes into authorized_keys like any other.
ssh-keygen -t ed25519-sk -C admin@laptop
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub admin@203.0.113.10
It is the right first step, and it is free. What it does not change is exposure: sshd still accepts connections from the whole internet and runs its pre-authentication code for each of them. A bug of the regreSSHion kind (CVE-2024-6387) is reached before any key is asked for.
2. A VPN in front
Put SSH on an address reachable only through a VPN, and port 22 disappears from the internet. WireGuard is especially good at this: it does not answer packets it cannot authenticate, so scanners do not see it either.
The price is a network to run: keys to distribute, routes, a client on every device, and trouble on guest networks that block UDP. And a WireGuard key is a file. There is no touch, no PIN and no second factor unless you add an identity layer on top.
3. Port knocking and single packet authorization
Classic port knocking (knockd) opens the port after a secret sequence of connection attempts. It hides the port, but the sequence travels in the clear and can be replayed by anyone who sees the traffic. Single packet authorization (fwknop) fixes that with one encrypted, non-replayable packet.
Both prove knowledge of a secret stored in a file on the client. Neither involves a hardware key or a person: malware on the admin's laptop can knock as well as the admin can.
4. A port that opens on a key touch
The newest variant keeps the idea of knocking and replaces the secret with a FIDO2 confirmation. The firewall drops the port; a small service verifies a WebAuthn signature from an enrolled key and opens the port for the caller's address for a short window.
RDP-FIDO-GATE works this way. On a Linux server sudo rdpfido-gate ports add 22 puts SSH — and up to 16 TCP ports — behind the same key that guards Remote Desktop, and the client starts ssh right after the touch. Setup takes about ten minutes: see the step-by-step guide.
There are also open-source projects that do the knock in a browser with a passkey. They need no client program; they do need a public HTTPS endpoint with a valid certificate on the server.
Side by side
| ed25519-sk keys | VPN (WireGuard) | Knocking / SPA | Key-gated port | |
|---|---|---|---|---|
| Port 22 answers strangers | Yes | No | No | No |
| Key touch for each connection | Yes | No | No | Yes |
| Shields sshd from pre-auth bugs | No | Yes | Yes | Yes |
| Extra software on the server | None | VPN endpoint | knockd or fwknopd | Gate service |
| Extra software on the client | None (OpenSSH 8.2+) | VPN client | Knock client | Gate client |
| Works where UDP is blocked | Yes | Often not | fwknop uses UDP by default | Yes (TLS over TCP) |
| New surface it exposes | None | A VPN port that stays silent | None, or a silent listener | The gate port, which answers TLS |
| Cost | Free | Free | Free | Free up to 10 sessions, then a one-time licence |
Which to choose
- One server, one admin, nothing to install: ed25519-sk keys. Do this in any case.
- A whole private network to reach — file shares, databases, internal sites: a VPN.
- A few admin ports on internet-facing servers, reached from changing addresses, with a real key touch each time: a key-gated port.
- Combinations beat any single choice. Security-key SSH keys inside sshd plus a gate or a VPN in front mean that a pre-auth bug and a stolen key file both fail.