Security

Disable Weak SSH Ciphers and MAC Algorithms on a Linux VPS

Edit sshd_config to allow only modern ciphers, MACs and key exchange algorithms, then verify the negotiation and keep a fallback session open.

AdvancedLinux server6 min read

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:

Bash
ssh -V

Warning: 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:

Bash
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:

Bash
nmap -p 22 --script ssh2-enum-algos 203.0.113.10

If 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:

Bash
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)

Now check whether your distribution includes a drop-in directory:

Bash
grep -i '^Include' /etc/ssh/sshd_config

If 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:

Bash
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
EOF

If 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-sha256 is the fastest and strongest key exchange most clients support. The diffie-hellman-group*-sha512 entries keep older enterprise clients and some network appliances working.
  • The -etm MACs (encrypt-then-MAC) are preferred because they authenticate the ciphertext before decrypting it.
  • aes256-ctr and 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* and diffie-hellman-group1-sha1 are gone.

Apply the change without locking yourself out

Test the syntax before reloading. This catches typos that would otherwise stop sshd from starting:

Bash
sudo sshd -t

No output means the file is valid. Now confirm the running config will use your values:

Bash
sudo sshd -T | grep -Ei 'ciphers|macs|kexalgorithms'

Reload rather than restart, so existing sessions stay alive:

Bash
sudo systemctl reload sshd

On 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:

Bash
ssh deploy@203.0.113.10

If 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:

Bash
sudo sshd -T | grep -Ei 'ciphers|macs|kexalgorithms'

Client side — what was actually negotiated for your connection:

Bash
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:

Bash
ssh -o Ciphers=aes128-cbc deploy@203.0.113.10

Expected 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-sha256 to KexAlgorithms or aes256-ctr to Ciphers, run sudo 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 -t to see the exact line, fix it, or restore with sudo cp /etc/ssh/sshd_config.bak.YYYY-MM-DD /etc/ssh/sshd_config and delete the drop-in.
  • Legacy device, switch or backup appliance can no longer connect. Older embedded SSH stacks often cap out at hmac-sha1 and aes128-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 ciphers and 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-sha256 because 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:

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.