CoursesLinux hardeningAccess hardening

Keys, MFA & bastions

Strong auth and a single front door.

Intermediate12 min · lesson 2 of 16

If keys are your only authentication, the keys themselves become critical. Generate modern ones — ed25519 is the current best default (small, fast, strong) — protect the private key with a passphrase so a stolen key file is not immediately usable, and keep private keys on the client only, never on the server. The server holds only public keys, in each user’s ~/.ssh/authorized_keys, which is why a compromised server does not leak the ability to log in elsewhere.

ONE FRONT DOOR: THE BASTION PATH
1Client (laptop)
private key + passphrase, held in ssh agent
2ProxyJump via bastion
ssh app-01 hops through transparently
3Bastion (edge)
one hardened, heavily-monitored gateway
4Internal host
firewall allows :22 ONLY from the bastion
Internal hosts accept SSH only from the bastion, collapsing the attack surface to one monitored gateway.
terminal
$ ssh-keygen -t ed25519 -C "deploy@laptop" # generate a modern keypair (with a passphrase!)
$ ssh-copy-id deploy@server # install YOUR public key on the server
# on the server, the public key lands here (mode must be tight):
$ ls -la ~/.ssh/authorized_keys
-rw------- 1 deploy deploy ... authorized_keys # 600, owned by the user — SSH enforces this

Add a second factor

For sensitive systems, a key alone can be strengthened to two factors. Hardware-backed keys (a FIDO2/U2F security key, using ed25519-sk) require the physical token to be present and touched, so a copied key file is useless without the hardware. Alternatively, a PAM TOTP module adds a one-time code on top of the key. The principle is defense in depth on your one remaining auth path: something you have (the key) plus something you physically possess or know.

terminal
# a hardware-backed key — the private key cannot be copied off the token
$ ssh-keygen -t ed25519-sk -C "deploy@yubikey"
# authentication now requires the physical security key to be present and tapped

A bastion: one front door

Rather than exposing SSH on every server to the internet, put one hardened jump host (a bastion) at the edge and reach everything else through it. Internal servers accept SSH only from the bastion’s network, so the attack surface collapses from "every host on port 22" to "one heavily-monitored gateway." SSH’s ProxyJump makes this transparent — you type one command and it hops through the bastion — and the bastion becomes the single place to log, audit, and enforce access.

~/.ssh/config
Host bastion
HostName bastion.acme.internal
User deploy
Host app-*
ProxyJump bastion # ssh app-01 transparently hops through the bastion
User deploy
# internal hosts’ firewalls allow port 22 ONLY from the bastion’s address
A leaked private key is a leaked login
The whole model rests on private keys staying private, so treat them like the credentials they are: passphrase-protect them, never commit one to a repo or copy it to a server, use an SSH agent rather than scattering keys, and remove a user’s public key from authorized_keys the moment they leave. An unprotected private key on a shared machine is exactly as bad as a shared password — the strong crypto does not help if the key itself walks out the door.