SSH Cookbook: Temporarily Disable Security Message on Connection to a Remote Server

First off, DO NOT do this all the time. ONLY do this when you have evaluated the risks and decided to risk a security breach anyways. I usually do this in my testing environment where I get to work with a lot of new or changing VMs.

When you connect for the first time to a server you are prompted to verify its fingerprint. It is then added to your ~/.ssh/known_hosts file so when you connect the next time and the fingerprint matches you are not prompted again. For example:

The authenticity of host ' (' can't be established.
RSA key fingerprint is 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00.
Are you sure you want to continue connecting (yes/no)?

This can be annoying when you connect to a lot of “new” SSH servers. It also doesn’t work in test environments where scripts need to continously connect to machines they have not connected to before and may not ever connect again. This can be even more annoying when the same IP is recycled between various test machines and your client machine does not connect because a known host’s fingerprint changed.

You can temporarily disable fingerprint matching at the time you are connecting:

ssh myuser@ -o CheckHostIP=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null

You can also put this config in your ~/.ssh/config file so that you don’t need to provide these extra flags all the time:

Host myhost
    Port 22
    User myuser
    AddressFamily inet
    CheckHostIP no
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

Now when you connect to the server you will see a message similar to this one:

Warning: Permanently added '' (RSA) to the list of known hosts.

It hasn’t actually added it to the known hosts file and that’s the beauty of it.

One last thing: DO NOT do this when connecting to machines you absolutely must trust. It’s alright to use this technique when connecting within a test lab environment, for example.

Secure Your SSH

So you have your SSH server on Linux up and running and you are able to login easily. But you may still be vulnerable to attacks on your SSH server, primary being brute force dictionary attacks. This post will point out some areas of vulnerabilities and also advise some solutions.

Only Allow Certain Users to Login via SSH

Your Linux machine has many users built into it. But only some of them need to have access to the server via SSH. If we can lock down a list of such users, we can reduce the number of users an attacker can pretend to be. For example, there are only three users on my machine who need to login. The good thing is that SSH allows you to setup either a list of users or a group of users who are allowed access.

I prefer the group method. The idea is to create a new Linux group and add users to it. If a user is a member of this group then he/she can login via SSH. If they are not a member they cannot. Then in the sshd config file we can specify this group as being the only one with access. Here’s how we do it.

Create a group
sudo groupadd mysshgroup

Add an existing user to this group. Thanks to Howto: Linux Add User To Group.
sudo usermod -a -G mysshgroup codeghar

Allow access only to this group in /etc/ssh/sshd_config file by making sure the following line exists in it.
AllowGroups mysshgroup

Disable root Login

Everyone who knows Linux knows there’s always a root user. So all the attackers out there know they just need to break its password to gain (complete) access to the system. What if we disallow root from logging in directly? This cuts down on a huge threat to your system.

Disable root login in /etc/ssh/sshd_config file by making sure the following line exists in it.
PermitRootLogin no

Disable Empty Password

Now that we have disallowed all users except those in the mysshgroup group to login, we have to make sure these users do not use empty passwords. If we don’t restrict this, a user, say codeghar, might have an empty password and an attacker can login very easily. We don’t want that.

Disable empty passwords in /etc/ssh/sshd_config file by making sure the following line exists in it.
PermitEmptyPasswords no

Allow Public Key Authentication Only

This means that we disable password-based authentication and only use public key authentication. This completely eliminates dictionary attacks because we just don’t use passwords. This requires a few extra steps, as explained below. Thanks to Setting up public key authentication over SSH for this part of the post.

On your client machine, you need to generate a new public and private key pair using RSA as encryption type and key strength as 4096 bits. You will be asked for a password. You can leave it blank but I recommend you put something in there. The reason is that if your private key gets into the wrong hands, they still need a password to be able to use it.
ssh-keygen -t rsa -b 4096

Now that a public/private key pair has been generated, you can use the keys. You first need to copy the public key from your client machine to your ssh server machine. You copy it to the user’s home directory on the server in the .ssh directory. For example, on the server you would need to copy it to /home/codeghar/.ssh/ directory. If it doesn’t exist, create it.
scp /home/codeghar/.ssh/

On the remote server, do the following so that the public key is appended to the authorized keys file
cat /home/codeghar/.ssh/ >> /home/codeghar/.ssh/authorized_keys

Now you can remove the original file because it’s no longer needed.
rm /home/codeghar/.ssh/

This has to be done for each client and also for each allowed user on the server. For example, if user codeghar uses two client machines, he/she needs to generate these pairs on each machine and then copy over the public key to the server. And if the server has two allowed users, both need to have these public keys in their own authorized keys files for them to be able to login.

You have copied over the public key but you still need to tell ssh to only use this key for authentication. Disable password authentication and enable public key authentication in /etc/ssh/sshd_config file by making sure the following lines exist in it.
RSAAuthentication yes
PubkeyAuthentication yes
PasswordAuthentication no

Activate Your Changes

You are now ready to activate these changes. Be aware that if you activate these changes and you made a mistake somewhere, you may lose all access. For this reason, establish an ssh connection first for the ‘just in case’ scenario and do not logout unless you are satisfied all things are working as they should.

To activate the changes, run the following command:
sudo /etc/init.d/ssh restart

Test the changes you have made so far by trying to login using a user who is not in the mysshgroup group, by logging in as root, and by using password authentication. All should work well.

If you are still asked for a password, or you get a Permission denied (publickey) error, then the ssh daemon/process thinks the settings of .ssh directory and/or the authorized_keys file on the server are insecure. To remedy the situation, you should change the permissions as below (hat tip: Public and Private Keys):

chmod 700 /home/codeghar/.ssh
chmod 600 /home/codeghar/.ssh/authorized_keys

Throttle ssh Connections

Although you have taken the aforementioned steps to make your server more secure, attackers are still going to attempt. With the above changes you should be secure but I prefer to add another layer: iptables firewalling. The idea is to restrict three attempts per minute for a new ssh connection from a single IP. This way you still have the ability to try three times a minute in case you provide wrong credentials. But it also means an attacker is restricted to three attempts per minute per IP. It doesn’t completely eliminate brute force attacks but it ought to slow these down.

You need the following three rules. Thanks to Using iptables to rate-limit incoming connections for helping with this section.
sudo iptables --append INPUT --protocol tcp --match tcp --destination-port 22 --in-interface eth0 --match state --state NEW --match recent --set
sudo iptables --append INPUT --protocol tcp --match tcp --destination-port 22 --in-interface eth0 --match state --state NEW --match recent --update --seconds 60 --hitcount 4 -j DROP
sudo iptables --append INPUT --protocol tcp --match tcp --destination-port 22 --jump ACCEPT

The first rule adds the IP of the client machine which initiates a new ssh connection. The second rule checks if this IP has attempted four or more connections in the past 60 seconds. If it has, this attempt is dropped. If it hasn’t, then it is allowed to ssh using the third rule. This way you get to try three times per minute but the fourth and subsequent attempts are blocked for a whole minute.

Other useful resources are: SSH Dictionary Attack Prevention with iptables; ssh – authorized_keys HOWTO; Throttling SSH attacks with pf; Port Knocking – A Cure for the Common SSH Login Attack;

SSH Login Takes a Long Time

Has it ever happened to you that logging in to an SSH server takes a long time? More than, say 20, 30 seconds? Well, there are many solutions out there to fix it, some may even make your system less secure. So let’s go to the source of SSH, so to speak, for a resolution. If you head over to ssh(1) takes a long time to connect or log in, you will see that it’s an issue with DNS resolution. To resolve this issue, try the following steps:

You need to change the sshd config file (on the server) …

sudo vim /etc/ssh/sshd_config

… and make sure you have this line uncommented

UseDNS no

Save the file and restart SSH daemon (service) like so

sudo service sshd restart (Fedora, Red Hat, CentOS)


sudo /etc/init.d/sshd restart (Debian, Ubuntu)

Hat tip: Slow SSH login;

Quick Introduction to Advanced SSH

I will not go through the complete overview of advanced SSH. For that, you may either use a search engine or read the following articles: SSH Advanced Techniques; Advanced SSH Usage; SSH Host Key Protection; ssh-keygen Tutorial; and SSH authorized_keys howto. What I will provide, though, are three quick commands:

Generate new public/private key pair, using RSA as encryption type and key strength as 4096 bits:
ssh-keygen -t rsa -b 4096

Change the passphrase used in the key
ssh-keygen -f id_rsa -p

Check the fingerprint of a public key
ssh-keygen -f -l