Basic configuration
There are a few basic things that most admins will already know (and that tiger will warn you about if you forget):
- only allow version 2 of the protocol
- disable root logins
- disable password authentication
This is what /etc/ssh/sshd_config should contain:
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
UsePrivilegeSeparation sandbox
AuthenticationMethods publickey
PasswordAuthentication no
PermitRootLogin no
Once you've done that, make sure you have all of the required host keys by running:
ssh-keygen -A
as root.
You may also want to ensure you are using strong ciphers and hash functions:
KexAlgorithms <insert Mozilla list>
Ciphers <insert Mozilla list>
MACs <insert Mozilla list>
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:
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.
Using restricted shells
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 set their shell
(via chsh) to a restricted one like
rssh.
Should they attempt to log into the server, these users will be greeted with the following error message:
This account is restricted by rssh.
Allowed commands: rsync
If you believe this is in error, please contact your system administrator.
Connection to server.example.com 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 following options to each entry:
no-X11-forwarding, no-user-rc, no-pty, no-agent-forwarding and
no-port-forwarding.
Increasing the amount of logging
Ff you run logcheck
and would like to whitelist the "Accepted publickey" messages on your
server, you'll have to start by deleting the first line of
/etc/logcheck/ignore.d.server/sshd. Then you can add an entry for all of
the usernames, IP addresses and ssh keys that you expect to see.
Finally, it is also possible to
log all commands issued by a specific user over ssh
by enabling the pam_tty_audit module in /etc/pam.d/sshd:
session required pam_tty_audit.so enable=francois
However this module is not included in wheezy and has only recently been re-added to Debian.
Identitying stolen keys
One thing I'd love to have is a way to identify a stolen public key. Given the IP
restrictions described above, if a public key is stolen and used from a different IP,
I will see something like this in /var/log/auth.log:
sshd: Connection from 198.51.100.10 port 39492
sshd: Authentication tried for francois with correct key but not from a permitted host (host=198.51.100.10, ip=198.51.100.10).
sshd: Failed publickey for francois from 198.51.100.10 port 39492 ssh2
sshd: Connection closed by 198.51.100.10 [preauth]
So I can get the IP address of the attacker (likely to be a random VPS or a Tor exit node), but unfortunately, the key fingerprints don't appear for failed connections like they do for successful ones. So I don't know which key to revoke.
Is there any way to identify which key was used in a failed login attempt or
is the solution to only ever have a single public key in each
authorized_keys file and create a separate user account for each user?
You might enjoy snoopy for logging purposes, since:
The downside is that it won't log stdin, but I'd suggest that's almost a benefit since it avoids root-access users from seeing passwords.
You can also use 2facthor auth with ( for example ) google authenticator:
http://www.howtogeek.com/121650/how-to-secure-ssh-with-google-authenticators-two-factor-authentication/