Best practices to harden and increase security with ssh (ciphers, MACs etc)

In my another article I have shared the steps to configure SSH port forwarding and tunnelling in Linux

Below are some of the selected arguments which can be used in sshd_config to harden the ssh based security. There can be many more such arguments which you can find from man page of sshd_config


A host key is a cryptographic key used for authenticating computers in the SSH protocol.
Host keys are key pairs, typically using the RSA, DSA, or ECDSA algorithms. Public host keys are stored on and/or distributed to SSH clients, and private keys are stored on SSH servers

For example:

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key


Specifies whether sshd separates privileges by creating an unprivileged child process to deal with incoming network traffic.  After successful authentication, another process will be created that has the privilege of the authenticated user.  The goal of privilege separation is to prevent privilege escalation by containing any corruption within the unprivileged processes.  The argument must be yes, no, or sandbox.  If UsePrivilegeSeparation is set to sandbox then the pre-authentication unprivileged process is subject to additional restrictions.  The default is sandbox.

For example:

UsePrivilegeSeparation sandbox


The server disconnects after this time if the user has not successfully logged in.  If the value is 0, there is no time limit.  The default is 120 seconds.

For example:

LoginGraceTime 60


Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon.  Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection.  The default is 10:30:100.

For example:

MaxStartups 200


Specifies whether root can log in using ssh.  The argument must be yes, prohibit-password, without-password,forced-commands-only, or no.  The default is yes.

If this option is set to prohibit-password or without-password, password and keyboard-interactive authentication are disabled for root. If this option is set to forced-commands-only, root login with public key authentication will be allowed, but only if the command option has been specified (which may be useful for taking remote backups even if root login is normally not allowed).  All other authentication methods are disabled for root.

If this option is set to no, root is not allowed to log in.

For example:

PermitRootLogin without-password


Specifies whether sshd should check file modes and ownership of the user's files and home directory before accepting login.  This is normally desirable because novices sometimes accidentally leave their directory or files world-writable. The default is yes.  Note that this does not apply to ChrootDirectory, whose permissions and ownership are checked unconditionally.

For example:

StrictModes yes


When password authentication is allowed, it specifies whether the server allows login to accounts with empty password strings.  The default is no.

For example:

PermitEmptyPasswords no


Specifies whether sshd should print /etc/motd when a user logs in interactively.  (On some systems it is also printed by the shell, /etc/profile, or equivalent.)  The default is yes.

For example:

PrintMotd no


Specifies whether sshd should print the date and time of the last user login when a user logs in interactively.  The default is yes.

For example:

PrintLastLog yes


Enables the Pluggable Authentication Module interface.  If set to yes this will enable PAM authentication using ChallengeResponseAuthentication and PasswordAuthentication in addition to PAM account and session module processing for all authentication types. Because PAM challenge-response authentication usually serves an equivalent role to password authentication, you should disable either PasswordAuthentication or ChallengeResponseAuthentication.

If UsePAM is enabled, you will not be able to run sshd(8) as a non-root user.  The default is no.

For example:

UsePAM yes

Encryption hardening using Ciphers, MACs, KexAlgorithms

We can harden the underlying encryption mechanism used by ssh. For performing ssh we can define the security algorithms which must be considered and used by the ssh

SSH can be configured to utilize a variety of different symmetrical cipher systems, including AES, Blowfish, 3DES, CAST128, and Arcfour. The server and client can both decide on a list of their supported ciphers, ordered by preference. The first option from the client's list that is available on the server is used as the cipher algorithm in both directions.

For example:

Ciphers aes128-ctr,aes192-ctr,aes256-ctr

MAC is another form of data manipulation that SSH takes advantage of is cryptographic hashing. Each message that is sent after the encryption is negotiated must contain a MAC so that the other party can verify the packet integrity. The MAC is calculated from the symmetrical shared secret, the packet sequence number of the message, and the actual message content.

For example:

MACs hmac-sha2-512,hmac-sha2-256,hmac-ripemd160

KexAlgorithms are the key exchange methods that are used to generate per-connection keys. If the client and server are unable to agree on a mutual set of parameters then the connection will fail

For example:

KexAlgorithms diffie-hellman-group-exchange-sha256


Specifies whether ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd.  The default is no.  Enabling environment processing may enable users to bypass access restrictions in some configurations using mechanisms such as LD_PRELOAD

For example:

PermitUserEnvironment no


Specifies the maximum number of open shell, login or subsystem (e.g. sftp) sessions permitted per network connection. Multiple sessions may be established by clients that support connection multiplexing.  Setting MaxSessions to 1 will effectively disable session multiplexing, whereas setting it to 0 will prevent all shell, login and subsystem sessions while still permitting forwarding.  The default is 10.

For example:

MaxSessions 10


Specifies whether the system should send TCP keepalive messages to the other side.  If they are sent, death of the connection or crash of one of the machines will be properly noticed.  However, this means that connections will die if the route is down temporarily, and some people find it annoying.  On the other hand, if TCP keepalives are not sent, sessions may hang indefinitely on the server, leaving "ghost" users and consuming server resources.

The default is yes (to send TCP keepalive messages), and the server will notice if the network goes down or the client host crashes.  This avoids infinitely hanging sessions.

To disable TCP keepalive messages, the value should be set to no.

For example:

TCPKeepAlive yes


Specifies the maximum amount of data that may be transmitted before the session key is renegotiated, optionally followed a maximum amount of time that may pass before the session key is renegotiated.  The first argument is specified in bytes and may have a suffix of âKâ, âMâ, or âGâ to indicate Kilobytes, Megabytes, or Gigabytes, respectively.  The default is between 1G and â4Gâ, depending on the cipher.  The optional second value is specified in seconds and may use any of the units documented in the TIME FORMATS section.  The default value for RekeyLimit is default none, which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done.

For example:

RekeyLimit 1G 1300


The contents of the specified file are sent to the remote user before authentication is allowed.  If the argument is none then no banner is displayed.  By default, no banner is displayed

For example:

Banner /etc/motd


Specifies the local addresses sshd should listen on. The default is to listen on all local addresses.  Multiple ListenAddress options are permitted.

For example:



This keyword can be followed by a list of group name patterns, separated by spaces.  If specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns.

For example:

AllowGroups wheel sdf root onends_group


This keyword can be followed by a list of user name patterns, separated by spaces.  If specified, login is allowed only for user names that match one of the patterns.

For example:

AllowUsers deepak ankit

I hope the article was useful.