Changing the SSH cipher list controls which encryption algorithms protect remote shells, SFTP transfers, and forwarded traffic. Adjusting that list is useful when older ciphers need to be removed, when a host should prefer a faster modern option, or when a server must match a security baseline.
OpenSSH negotiates one cipher in each direction during session setup. On current Ubuntu and Debian systems, the server-side Ciphers directive is usually set in /etc/ssh/sshd_config or a file under /etc/ssh/sshd_config.d, while clients can override their own preference in /etc/ssh/ssh_config or ~/.ssh/config. ssh -Q cipher shows the ciphers compiled into the local build, sshd -T shows the effective server policy, and ssh -G shows the effective client policy for a target host.
Examples below use the current Ubuntu and Debian package layout and a standard per-user OpenSSH client config. OpenSSH uses the first value it reads for most directives, so conflicting Ciphers lines in the main file and snippet files can quietly override later edits; test the daemon with sshd -t, keep another administrative path open, and confirm the negotiated cipher from a separate client before closing the working session.
Steps to change SSH ciphers on the server:
- Open a terminal on the SSH server with an account that can use sudo.
- List the ciphers supported by the installed OpenSSH build.
$ ssh -Q cipher 3des-cbc aes128-cbc aes192-cbc aes256-cbc aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com
ssh -Q cipher lists every cipher compiled into the client, including legacy CBC names that are not part of the current default server policy.
- Check the current cipher list that sshd will offer.
$ sudo sshd -T | grep '^ciphers ' ciphers chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
sshd -T expands included files and defaults, so it is the most direct way to confirm the active server policy before and after an edit.
- Check whether the main server config loads a snippet directory.
$ grep -n '^Include' /etc/ssh/sshd_config 12:Include /etc/ssh/sshd_config.d/*.conf
On Ubuntu and Debian, a dedicated snippet file such as /etc/ssh/sshd_config.d/10-ciphers.conf is usually cleaner than editing the main file directly.
- Open the server config location that should carry the Ciphers directive.
$ sudoedit /etc/ssh/sshd_config.d/10-ciphers.conf
If the system does not load /etc/ssh/sshd_config.d, edit /etc/ssh/sshd_config instead.
- Add or update one active Ciphers line with the policy that the server should offer.
/etc/ssh/sshd_config.d/10-ciphers.conf Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr
Use one active Ciphers directive for the final server policy. A list that begins with + appends names to the defaults, - removes names from the defaults, and ^ moves names to the front of the default order.
- Validate the updated SSH daemon configuration.
$ sudo sshd -t
No output means the configuration parsed successfully.
Keep a second SSH session or console open until the new policy has been tested from a separate client.
Related: How to test SSH server configuration
- Restart the SSH service so the daemon reads the new cipher list.
$ sudo systemctl restart ssh
On RHEL-family systems, the unit is commonly named sshd, so the equivalent command is sudo systemctl restart sshd.
- Confirm that the running daemon now exposes the updated cipher list.
$ sudo sshd -T | grep '^ciphers ' ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr
- From a separate client, open a verbose test connection and check the negotiated cipher.
$ ssh -vv user@host.example.net 'exit' ##### snipped ##### debug1: kex: server->client cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none debug1: kex: client->server cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none ##### snipped #####
The two kex lines show the cipher actually selected for the session.
If the client and server no longer share any cipher, the connection fails with a no matching cipher found negotiation error until at least one common algorithm is restored.
Steps to change SSH ciphers on the client:
- Open the per-user OpenSSH client config file, or create it if it does not already exist.
$ nano ~/.ssh/config
A host-specific override changes the cipher order for one target without affecting every other SSH connection from the client. Use /etc/ssh/ssh_config only when every user on that system should share the same client policy.
- Add or update a host block with the cipher list that should be offered for that target.
~/.ssh/config Host host-cipher HostName host.example.net User user Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr
- Restrict access to the per-user SSH config file.
$ chmod 600 ~/.ssh/config
OpenSSH expects private per-user config files to be writable only by the account that owns them.
- Show the effective client cipher list for that host alias.
$ ssh -G host-cipher | grep '^ciphers ' ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr
ssh -G prints the final client configuration after the matching Host block has been applied.
- Make a verbose test connection and confirm the cipher that was actually negotiated.
$ ssh -vv host-cipher 'exit' ##### snipped ##### debug1: kex: server->client cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none debug1: kex: client->server cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none ##### snipped #####
The server→client cipher and client→server cipher lines confirm that the client preference and the server policy still overlap.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
