To disable weak SSH ciphers and MAC algorithms you edit /etc/ssh/sshd_config (or a drop-in file in /etc/ssh/sshd_config.d/), list only the modern algorithms you want to allow, test the config with sshd -t, and reload the service. This guide takes you from the default algorithm list on Ubuntu, Debian, AlmaLinux or Rocky to a short, current set, then shows how to confirm the negotiation and how to get back in if a client can no longer connect.
The reason to do this is simple: old ciphers such as aes128-cbc and MACs such as hmac-md5 are still offered by many default SSH installs, and they are the first thing a scanner flags. Removing them costs you nothing on modern clients and shrinks the attack surface.
Before you start
You need:
- A Linux VPS with SSH access and a user that can run
sudo. - A second way in, in case you lock yourself out. The browser console in your VPS provider's control panel counts — open it in a tab before you touch the config.
- A recent SSH client on your own machine. OpenSSH 8.x and 9.x on Linux, macOS and Windows 10/11 handles everything below.
Check the client version first:
ssh -VWarning: You are changing the algorithm set that every SSH client must match. Keep one working session open while you test, and only close it after a fresh connection succeeds.
See which algorithms the server offers
Before changing anything, record the current state. Run this on the server:
sudo sshd -T | grep -Ei 'ciphers|macs|kexalgorithms'You will see comma-separated lists. Anything ending in -cbc, plus hmac-md5, hmac-sha1 and diffie-hellman-group1-sha1, is a candidate for removal.
You can also list what the server advertises from outside, which is what a scanner sees:
nmap -p 22 --script ssh2-enum-algos 203.0.113.10If you prefer a dedicated tool, ssh-audit reports ciphers, MACs, key exchange and host key algorithms in one pass. It is packaged in most distributions and also available from PyPI; install it the way your distribution documents, since packaging changes over time.
Save the output somewhere. It is your before-and-after proof.
Disable weak SSH ciphers and MAC algorithms in sshd_config
Back up the file first:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)Now check whether your distribution includes a drop-in directory:
grep -i '^Include' /etc/ssh/sshd_configIf you see Include /etc/ssh/sshd_config.d/*.conf, create a drop-in file. Because sshd uses the first value it obtains and the Include line sits near the top of the file, the drop-in wins:
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf > /dev/null <<'EOF'
# Modern algorithm set - review after major OpenSSH upgrades
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256
EOFIf there is no Include line, append the same block to the end of /etc/ssh/sshd_config instead.
A few notes on the choices:
curve25519-sha256is the fastest and strongest key exchange most clients support. Thediffie-hellman-group*-sha512entries keep older enterprise clients and some network appliances working.- The
-etmMACs (encrypt-then-MAC) are preferred because they authenticate the ciphertext before decrypting it. aes256-ctrand friends stay in the list for compatibility with older tooling and libraries. Drop them only if you know every client you use supports AES-GCM or ChaCha20.- The CBC ciphers,
hmac-md5*,hmac-sha1*,umac-64*anddiffie-hellman-group1-sha1are gone.
Apply the change without locking yourself out
Test the syntax before reloading. This catches typos that would otherwise stop sshd from starting:
sudo sshd -tNo output means the file is valid. Now confirm the running config will use your values:
sudo sshd -T | grep -Ei 'ciphers|macs|kexalgorithms'Reload rather than restart, so existing sessions stay alive:
sudo systemctl reload sshdOn Debian and Ubuntu the unit is called ssh, so use sudo systemctl reload ssh. If reload is not supported, sudo systemctl restart sshd works but drops current connections — that is why the console tab matters.
Leave your current session open and open a second terminal:
ssh deploy@203.0.113.10If it connects, you are done. If not, use the browser console from your VPS provider's control panel and restore the backup.
Check it works
Verify from both sides.
Server side — what sshd now offers:
sudo sshd -T | grep -Ei 'ciphers|macs|kexalgorithms'Client side — what was actually negotiated for your connection:
ssh -vvv deploy@203.0.113.10 2>&1 | grep -E 'kex: algorithm|kex: host key algorithm|cipher:|MAC:'You should see chacha20-poly1305@openssh.com or an AES-GCM cipher, an -etm MAC, and curve25519-sha256 for key exchange.
Negative test — ask for a cipher you removed. It must fail:
ssh -o Ciphers=aes128-cbc deploy@203.0.113.10Expected output:
Unable to negotiate with 203.0.113.10 port 22: no matching cipher found.Run ssh-audit 203.0.113.10 once more and compare with your earlier output. The weak entries should be gone.
Tip: Add the same restrictions to your own ~/.ssh/config for the hosts you connect to. That way your client never offers a weak algorithm first, and failures show up on your side rather than in the server log.
Troubleshooting
- "no matching key exchange method found" or "no matching cipher found" on connect. The client is too old for the set you allowed. On the server, add
diffie-hellman-group-exchange-sha256toKexAlgorithmsoraes256-ctrtoCiphers, runsudo sshd -t, reload, and retry. Update the client when you can. - sshd will not start after the change. A typo in the drop-in file. Use the console, run
sudo sshd -tto see the exact line, fix it, or restore withsudo cp /etc/ssh/sshd_config.bak.YYYY-MM-DD /etc/ssh/sshd_configand delete the drop-in. - Legacy device, switch or backup appliance can no longer connect. Older embedded SSH stacks often cap out at
hmac-sha1andaes128-cbc. Keep a separate listener for that device instead of weakening the main config: run a second sshd instance on another port with its own config file, and restrict it with a firewall rule to the device's IP. - The config file looks right but nothing changed. Another drop-in earlier in the directory sets the same option, and the first value wins. Check with
sudo sshd -T | grep -i ciphersand inspect files in/etc/ssh/sshd_config.d/in alphabetical order. - Connection works but is slow. You probably fell back to
diffie-hellman-group-exchange-sha256because the client does not support Curve25519. Update the client; the performance difference on a VPS is noticeable.
Next steps
Algorithm hardening is one layer. These guides cover the rest:
- Set up SSH keys so password guessing is not an option.
- Disable root login and password authentication over SSH to remove the easiest entry point.
- Protect SSH from brute-force attacks with Fail2ban to block repeated failures automatically.
- Rate-limit SSH and other ports with ufw limit for a second, kernel-level control.
