SSH setup on mkirby.org

The default OpenSSH settings on Fedora are pretty secure, but I like to add a few extra features.
Below are the extra settings I have in addition to the defaults.

1) I increase the log level to verbose.  The only benefit I see is for key auditing.  If a login uses an ssh key, its fingerprint will be logged to /var/log/secure.  As you can see from the log sample below, I used a valid key to log into my server.  It will only show the fingerprint of the key I used.

May 24 17:08:31 goemon sshd[53854]: Partial password for mkirby from 192.168.1.50 port 37137 ssh2
May 24 17:08:31 goemon sshd[53854]: Found matching ECDSA key: b4:5d:9e:74:cd:c6:f9:28:17:d1:b3:d6:ca:89:8b:49
May 24 17:08:31 goemon sshd[53854]: Accepted publickey for mkirby from 192.168.1.50 port 37137 ssh2: ECDSA b4:5d:9e:74:cd:c6:f9:28:17:d1:b3:d6:ca:89:8b:49

If I try to authenticate with an invalid key, it will log the fingerprint of the key that was attempted. This can be useful when a user complains that their ssh key isn’t working. You can match the fingerprint of the key they are trying to use with the key that is setup for their account. It can also be useful if you see the fingerprint of a known compromised key.

May 24 17:19:43 goemon sshd[53968]: Failed publickey for mkirby from 192.168.1.50 port 37183 ssh2: DSA bc:5d:88:98:23:25:88:1c:81:03:26:ed:66:2f:dd:4e

To find out the fingerprint of the keys in your authorized keys file, you can use ssh-keygen like so where -l means show the fingerprint and the authorized keys file is specified after the -f. I have my ssh key in a non-standard location, so you will probably want to specify your authorized_keys file in the user’s .ssh directory.

/ # ssh-keygen -l -f /etc/ssh/keys/mkirby
521 b4:5d:9e:74:cd:c6:f9:28:17:d1:b3:d6:ca:89:8b:49 mkirby@jigen.mk.lan (ECDSA)


2) I use a non-standard location for ssh keys. I store them in the /etc/ssh/keys/ directory where the filename is the username. This is setup in /etc/ssh/sshd_config like so: AuthorizedKeysFile /etc/ssh/keys/%uThe files are read-only and owned by the user. Usually that means that a user can add a new key by changing the permissions or forcing to write with an editor. On my system I use chattr to make the file immutable, which prevents the user from changing/adding/deleting their keys file even if they try to force write or change the file permissions. Only root can set the immutable flag on the files, so the user cannot undo the flag. The user has absolutely no control over their authorized ssh keys.

3) I setup 2-factor authentication on my ssh server so that both a password and an ssh key are required. If either are incorrect, the user will not authenticate.Here is the setting I have in sshd_config: AuthenticationMethods password,publickey keyboard-interactive,publickeyThat means that the server will first ask for a password and, if the password is valid, ask for the ssh key. Most documentation will say to use the opposite direction, where the key is first and then the password. I prefer password first because a brute-force password attack will not detect that an ssh key is also required. This not only makes the attack completely futile, but the attacker will just assume that none of the passwords were successful (even if they were). If the key were prompted before the password, the attacker would know that a brute-force password attack would fail. This method creates visibility for attacks and wastes time for the attacker (unless the attacker is reading this blog).Here is what my ssh login looks like. Notice that it says “Authenticated with partial success.” after prompting for the password. If I used the other authentication order, it would show that before prompting for the password. An attacker would see that and know that 2-factor is enforced.


# ssh goemon
mkirby@goemon’s password:
Authenticated with partial success.
Last failed login: Sat May 24 18:05:50 CDT 2014 from jigen.mk.lan on ssh:notty
There were 2 failed login attempts since the last successful login.
Last login: Sat May 24 17:40:17 2014 from jigen.mk.lan
[ ?0 goemon mkirby !636 &0 18:05:50 ]
~ #

The only problem with this setup is that it triggers 2 failed login attempts everytime I login. Just a minor annoyance. It still increments on failed password attempts, so I just need to be vigilant for greater than 2 failed logins.

4) Logins are restricted to a special group. By default, the ssh service will allow any user to authenticate. I set up my server so that only members of the wheel group are permitted to login. This prevents login access to non-user accounts that may have been compromised. To enable this, I put AllowGroups sshusers in the sshd_config. The only member of that group is my personal account.

5) Forwarding, tunneling, etc are disabled for obvious reasons.
Here are the settings I have in sshd_config:


AllowAgentForwarding no
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
PermitTunnel no


6) I enforce strong ciphers and hmacs. By default, many of the weaker ciphers and hmacs are enabled. The stronger ciphers are usually chosen first, but I like to enforce the strong ones. Some security vulnerability scans may flag the md5 hmacs as insecure, which is how I discovered these settings. I only enable the ciphers/hmacs I need to ssh with the OpenSSH, Putty, and SecureCRT clients. Putty and SecureCRT can’t use the newer and stronger ciphers/hmacs, so the weaker ones are listed after the stronger, more preferred.
Here are the settings in sshd_config:

ciphers aes256-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha1


7) I use 521-bit ECDSA keys for authentication. Prior to the newer OpenSSH, I used 4096-bit RSA keys. The default key is 1024-bit DSA. If you don’t know the difference between these key types, Google is your friend. The possible bit lengths for ECDSA is 256, 384, and 521. I’m no mathematician, but the 521-bit looks odd. At first I thought it was a typo of 512, but it is not. From what I’ve read, ECDSA is faster and arguably more secure than RSA even at a smaller key size. ECDSA uses elliptical curves and RSA uses primes. That’s as much as I want to know as far as the mathematics.
Here is how to create a 521-bit ECDSA key:

ssh-keygen -t ecdsa -b 521


8) I also use a 521-bit ecdsa hostkey and removed the other hostkeys. It will regenerate the rsa hostkey automatically, but it will only use the ecdsa hostkey.
Here is how to create a 521-bit ECDSA hostkey:

ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key

Here are the settings in sshd_config:

HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key


9) I restrict network access through TCP wrappers. Only the local network is allowed ssh access. There is already 2 firewalls in front of this webserver, so this only adds another layer of security. This is configured through /etc/hosts.allow and /etc/hosts.deny. I also have TCP wrappers spawn a logger to record some information about the connection. This is especially important for the hosts.deny as it can help with troubleshooting.
Here is my /etc/hosts.deny. I deny everything by default:

ALL: ALL: spawn (logger -p daemon.notice “TCPD_DENY %d from %a PID %p Service %s”) &

Here is my /etc/hosts.allow:

rpcbind: 192.168.0.0/16
sshd: 192.168.1.0/24: spawn ( logger -p daemon.notice “TCPD_ALLOW %d from %a PID %p Service %s”) &


10) I set PermitRootLogin no in sshd_config so that the root account cannot be logged into directly through ssh. To gain root access, I must log in with my personal account and sudo su to root.