These are the settings that I use to harden ssh on my servers and clients.
Basic server configuration
There are a few basic things that most admins will already know (and that tiger will warn you about if you forget):
- disable root logins
- disable password authentication
If you are using rkhunter, you will need
to disable the check for root logins since rkhunter doesn't check
non-default config files.
This is what I put in /etc/rkhunter.conf.local
:
ALLOW_SSH_ROOT_USER=unset
This is what my /etc/ssh/sshd_config.d/local.conf
contains:
AuthorizedKeysFile .ssh/authorized_keys
AcceptEnv LANG LC_* TZ
HostKey /etc/ssh/ssh_host_ed25519_key
KexAlgorithms curve25519-sha256@libssh.org,curve25519-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
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
AuthenticationMethods publickey
LogLevel VERBOSE
PermitRootLogin no
in order to also prevent the use of problematic or weak cryptographic algorithms.
Once you've done that, make sure you have all of the required host keys by running:
ssh-keygen -A
as root.
The above configuration is based on the Mozilla
recommendations
and then tightened up using the
ssh-audit
package.
While Mozilla recommends disabling short Diffie-Hellman moduli:
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp
mv /etc/ssh/moduli.tmp /etc/ssh/moduli
that ends up being very annoying since it causes merge conflicts on distro upgrades.
Finally, if you don't need sftp
support, Mozilla recommends disabling it,
which can be done by commenting out this line in /etc/ssh/sshd_config
:
#Subsystem sftp /usr/lib/openssh/sftp-server
On the other hand, if you do need it, it's generally better to replace it with the internal sftp server:
Subsystem sftp internal-sftp
Whitelist approach to giving users ssh access
To ensure that only a few users have ssh access to the server and that newly created users don't have it enabled by default, create a new group:
addgroup sshuser
and then add the relevant users to it:
adduser francois sshuser
Finally, add this to /etc/ssh/sshd_config.d/local.conf
:
AllowGroups sshuser
Deterring brute-force (or dictionary) attacks
One way to ban attackers who try to brute-force your ssh server is to
install the fail2ban
package. It keeps an eye on the ssh log file (/var/log/auth.log
) and
temporarily blocks IP addresses after a number of failed login attempts.
To prevent your own IP addresses from being blocked, add them to
/etc/fail2ban/jail.d/local.conf
:
[DEFAULT]
ignoreip = 127.0.0.1/8 1.2.3.4
Another approach is to hide the ssh service using Single-Packet Authentication. I have fwknop installed on some of my servers and use small wrapper scripts to connect to them.
Restricting shell access
For those users who only need an ssh account on the server in order to
transfer files (using scp
or rsync
), it's a good idea to restrict their
access further. I used to switch these users' shell (via chsh) to a restricted one like
rssh, but that project has been
abandoned.
I now use a different
approach
which consists of using an essentially empty chroot for these users and
limiting them to internal-sftp
by putting the following in
/etc/ssh/sshd_config
:
Match Group sftponly
ForceCommand internal-sftp
ChrootDirectory /mnt/data
creating a group:
adduser sftponly
and a base chroot directory:
mkdir -p /mnt/data/home
Note that the base directory, and each parent directory all the way to the
root directory, must be owned by root:root
(user and group) otherwise
you'll see an unhelpful error message like this when you try to connect via
sftp:
$ sftp user1@server.example
client_loop: send disconnect: Broken pipe
Then for each user, we need to do the following:
adduser user1 sftp-only
chsh user1 -s /bin/false
mkdir -p /mnt/data/home/user1
chown user1:user1 /mnt/data/home/user1
chmod 700 /mnt/data/home/user1
before restarting the ssh daemon:
systemctl restart sshd.service
Should one of these users attempt to connect via ssh instead of stp, they will see the following:
$ ssh user1@server.example
This service allows sftp connections only.
Connection to server.example closed.
Restricting authorized keys to certain IP addresses
In addition to listing all of the public keys that are allowed to log into a
user account, the ~/.ssh/authorized_keys
file also allows (as the
man page
points out) a user to impose a number of restrictions.
Perhaps the most useful option is from which allows a user to restrict the IP addresses which can login using a specific key.
Here's what one of my authorized_keys
looks like:
from="192.0.2.2" ssh-rsa AAAAB3Nz...zvCn bot@example
You may also want to include the restrict
option to each entry since it
will automatically disable powerful features.
Client configuration
Since servers can sometimes create outbound ssh connections, for example as
part of an offsite backup, I tighten up the ssh client configuration on all
of my machines by putting the following in
/etc/ssh/ssh_config.d/local.conf
:
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
KexAlgorithms curve25519-sha256@libssh.org,curve25519-sha256,diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,diffie-hellman-group14-sha256,diffie-hellman-group-exchange-sha256
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
again, based on the Mozilla recommendations modified according to the ssh-audit report.
Note that if you need to connect to Launchpad, you'll
need to relax these settings in your ~/.ssh/config
:
Host *.launchpad.net
HostKeyAlgorithms rsa-sha2-512
MACs hmac-sha2-512