Restrict SSH login using SSH keys to a particular IP address

SSH_Shell_key-restrictio_500The SSH connection to your server is one of the most important way of accessing and managing your server, because of this, it is a target for any attacker that wants access to your server. Securing SSH is therefore very important. As I have already described in Secure servers ssh access, there are a couple of precautions you can take to prevent attackers from guessing your password.

Since, if nothing else, it’s quite annoying to have to type passwords all the time, you might have already considered creating SSH-keys, and configured SSH passwordless login with SSH-key for your server.

If the SSH-key is compromised

If your ssh-key fell into the wrong hands, anybody could access your server from anywhere on the internet. Restricting the ssh-key is one possibility to reduce the risk of an attacker hacking into your server by obtaining the ssh-key. Of course, if an ssh-key has been compromised, it should be removed from all affected systems and replaced by a new one as soon as possible, but still, restricting the SSH-key in some way could avoid the worst scenario.

Restricting an SSH-Key

When you add a SSH-key to the server, you add it to the users .ssh/authorized_keys file. This file allows you to add the keys that are allowed to authenticate for this user, but the authorized_keys file allows much more then just adding the key. As I have already described in Subversion via ssh using authorized_keys, the authorized_keys file can be used to restrict the possibilities of the user when he is logging in with an SSH-Key.

The format of the .ssh/authorized_keys file is as follows:

options keytype base64-encoded-key comment

The SSH-key you add when you set up the SSH passwordless login with SSH-key already contains the “keytype”, “base64-encoded-key” and “comment”. That leaves the “options” where you can define a lot of ssh options for the key. As shown in SSH passwordless login with SSH-key the options can set a specific command to be run after login instead of a shell or the user can be restricted so he cannot perform certain actions.

When you use the following option, you can restrict where a user is allowed to login from using the SSH-key. To do so, add the option shown below to the line of the SSH-key. If you need multiple options, they should be separated by a “,”.

from="pattern-list"

The IP addresses or hostnames can be specified as a list in the ‘from’ pattern-list. The list is comma-separated and allows you to use the wildcards ‘*’ (a wildcard that matches zero or more characters) or ‘?’ (a wildcard that matches exactly one character). Such an authorized_keys line might then look like this:

from="10.0.0.?,*.example.com",no-X11-forwarding ssh-rsa AB3Nz...EN8w== user@example.com

The example line above would only allow the login from a client if it comes from an IP address in the range from 10.0.0.0 to 10.0.0.9 or with a host resolveable in the example.com domain. As the example shows, other options are separated with a comma.

Check the “AUTHORIZED_KEYS FILE FORMAT”section of the sshd(8) manpage  for a full list of options you can define in the authorized_keys file.

Disable password login

You probably want to disable password login to avoid someone logging in from somewhere else then the hosts you have configured in the authorized_keys file. To disable password authentication globally for all users, the following 3 settings need to be changed to “no” in the /etc/ssh/sshd_config file:

infoMake sure authentication with the SSH-key is working before you disable password login to avoid locking yourself out. Please make sure that the settings are not set twice within the sshd_config. Adding the following lines at the end of the sshd_config DOES NOT override previous lines defining the setting. To make sure your configuration works as expected, test the setup after you changed the configuration.
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no

If you want to disable the password authentication only for one user you have two options. The first is to configure the “PasswordAuthentication no” parameter in the /etc/ssh/sshd_config inside a “Match directive” to apply it only for a specific user, a list of users or a group.

infoThis does not work with sshd versions before 4.4 (See the OpenSSH 4.4 release notes). At the time of writing CentOS 5.10 uses OpenSSH 4.3 and so does not support the “Match directive”. CentOS 6.x includes OpenSSH 5.3 which supports “Match directive”. To determine the version of the SSH server running execute the following command.

$ ssh-keyscan -p 1234 host.example.com

The following Lines need to be added to the /etc/ssh/sshd_config to disable password login for one or more users. In the example below you can see a list of users provided in the Match directive:

Match User username1,username2,username3
    PasswordAuthentication no

If you need to disable password authentication for a group of users, the Match directive allows the following syntax to do this:

Match Group usergroup
    PasswordAuthentication no

If the ssh server version does not allow the use of the Match directive you can still disable password login for certain users by locking the user account. What the –lock option really does is that it changes the password (which is stored encrypted) to a value that will never match any encrypted password (The value “!”):

$ passwd --lock username1

With this locked user, you will still see the password prompt when you try to logon with them (with no SSH key), but whatever password you enter will never pass authentication. To unlock such an account, you would need to set a new password with this command:

$ passwd username1
Changing password for user username1.
New UNIX password: 
Retype new UNIX password: 
passwd: all authentication tokens updated successfully.

As with any configuration of the ssh server, the daemon needs to be notified of configuration changes. This can be done in two ways: you can notify the ssh daemon via the “reload” option, or you can restart the ssh server via the “restart” option. In both cases the open ssh session will stay connected.

Test your setup

As with any setting, you should test it to verify you did not miss any configuration. While configuring sshd of a remote server I’ve always found it handy to stay online with one session where you configure the server and, test access to the server with another local terminal. The ssh server will not kick you out of a connected session while reloading the configuration or restarting it. This can be useful in cases where you lock yourself out by misconfiguration. As long as the session stays open, you can still correct the configuration ,even if you can not login any more with a new session.

To verify that the ssh-key is limited to only your IP address, it can be handy to have another location from where you can try to login to verify the server is really rejecting the key:

$ ssh username1@server.example.com -v -i .ssh/ssh-key-file

With this command you will try to login using the ssh-key provided in the command line. The -v option will help us to see if the server properly rejects the ssh-key. When you execute the command above from a client that is allowed to use the ssh-key, you should be directly logged in and see the shell, but from any other location you should find lines similar to the following:

debug1: Offering RSA public key: /Users/username1/.ssh/ssh-key-file
debug1: Remote: Your host '123.123.123.123' is not permitted to use this key for login.

Those lines indicate that the key was rejected by the ssh server as they are not allowed to be used from this IP address or hostname.

To verify that the password authentication is not allowed, use a user that does not have an ssh-key in its ssh configuration and try to login to the server:

$ ssh username1@server.example.com
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

The error message here shows the allowed authentication methods. You can see that the “password” method is not listed in the message and indicates that you have successfully disabled the password login.


Read more of my posts on my blog at http://blog.tinned-software.net/.

This entry was posted in Linux Administration, Security and tagged , , , . Bookmark the permalink.