Saturday, June 18, 2011

SSH Hardening

One of the most common uses of remote management in the Linux world is SSH. In another post I talked about setting up an SSH server including a few tweaks to make it more secure. Today though I want to talk about SSH Hardening. Being that it is the most common way into a system it is important that you take the time to harden the service and review any log messages that may be produced. The first thing to look at when hardening SSH is the server's config file which can be found at /etc/ssh/sshd_config.

Lets look at a few options that should be changed in config file:

# Disallow users to forward ports from the server
AllowTcpForwarding no
# Explicitly allow only the follow users
AllowUsers
# The root user should never be able to log in remotely
DenyUsers root
DenyGroup root
PermitRootLogin no
# Don't read the rhosts file of clients
IgnoreRhosts yes
# Display a banner for users
Banner /etc/ssh_banner # You must create /etc/ssh_banner if it doesn't exist
# Send info to the syslog service
LogLevel INFO
# Don't allow anyone to log in without a password
PermitEmptyPasswords no
# Enforce using the more secure protocol (v2)
Protocol 2
# Don't allow X11 to forward anything
X11Forwarding no
# Change the default port to listen on
Port 222

This is a good set of options to configure your sshd_config file with to make the SSH service more secure. On top of locking down the service itself however there are other steps we can take to ensure more security for SSH. We can setup TCP Wrappers to only allow particular hosts or subnets to be able to access the SSH server remotely. The following assumes that I'm only allowing connections from the 172.168.1.x /24 network:

echo "sshd: 172.168.1." >> /etc/hosts.allow
echo "ALL: ALL" >> /etc/hosts.deny

This will allow all clients within the 172.168.1.x subnet to connect into the SSH server (provided they have a valid user account), and it will disallow anything else. One mistake that some people make is assuming this is a firewall, it is not! Conveniently the next topic to touch on is iptables however. For those that prefer the GUI interface there are dozens of utilities that interface with iptables to configure ports and services. Essentially you are going to need to create a rule which allows access to whatever port you have defined the SSH service to run on (port 222 for the example given above). For those following this guide and the command line oriented:

# -A RH-Firewall-1-INPUT -s 172.168.1.0/24 -m state --state NEW -p tcp --dport 222 -j ACCEPT

At this point you should be all set with the hardening for SSH. You will want to restart the iptables service and the SSH service so that all the new settings take effect, and then test out your connections.

# service iptables restart
# service sshd restart

Below is just a sample sshd_config file to show what it looks like with all the changes made. Most sshd_config files will be longer and have more options to set or choose from. Check the official documentation for a full list of options.

### Sample sshd_config File ###

# General Options
Port 222
Protocol 2
AllowTcpForwarding no
Banner /etc/ssh_banner
IgnoreRhosts yes
X11Forwarding no

# Logging
SyslogFacility AUTHPRIV
LogLevel INFO

# Authentication
PermitEmptyPasswords no
DenyUsers root
DenyGroups root
PermitRootLogin no
AllowUsers jsmith
UsePAM yes
PasswordAuthentication yes
ChallengeResponseAuthentication no

# GSSAPI options
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes

# Accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL

In a separate post we will talk about the use of public/private keys with SSH making the service even more secure and for home users, easier.


Previously we looked at ways to harden the SSH service and reviewed a number of options that can be used in the config file. Here we are going to look at public and private keys to make the SSH service more secure and possibly easier to use. With key authentication users will have a private key (on their local client machines) and a private key (on the server which they want to connect to). When the user goes to log into the server the two keys are used (with an optional passphrase) to allow the user to log in. There are a few steps involved with settings this up, and most importantly is knowing where the keys will be located:

~/.ssh/ -> is the location on the client machine where the private key is located
~/.ssh/authorized_keys -> is the location on the server where the public key is located

Lets look at the steps for setting up key authentication. Login to your client machine and execute the following:

$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/tc_user/.ssh/id_rsa): [Press Enter]
Created directory '/home/tc_user/.ssh'.
Enter passphrase (empty for no passphrase): [Enter a STRONG password]
Enter same passphrase again:
Your identification has been saved in /home/tc_user/.ssh/id_rsa.
Your public key has been saved in /home/tc_user/.ssh/id_rsa.pub.
The key fingerprint is:
8f:a2:03:e9:5b:df:52:a4:8d:80:ad:3b:50:01:7e:23 tc_user@localhost.localdomain

Here you can see both the private and public key being generated. You should cd over into ~/.ssh and use ls -l to check and make sure that you are the only user that has read/write access to your private key.

$ cd ~/.ssh
$ ls -l
total 8
-rw------- 1 tc_user tc_user 1743 Apr  8 10:32 id_rsa
-rw-r--r-- 1 tc_user tc_user  411 Apr  8 10:32 id_rsa.pub 
 
Now that your private key is in place and secured from other users viewing it you will need to take your public key and give it to your system admin. We are going to assume that you are the admin, so you will take the public key of the user and copy the contents of it into the users account on the server under the authorized_keys file. You should also secure this file:

$ cat ./id_rsa.pub >> /home/tc_user/.ssh/authorized_keys
$ chmod 600 /home/tc_user/.ssh/authorized_keys

There is one final change that you should make on the server. In the /etc/ssh/sshd_config file change the following two options:

PasswordAuthentication no
PubKeyAuthentication yes

This will prevent users from logging on with anything but their public/private key combination. Reload the SSH server for the settings to take effect. Now you should be all set! Assuming that you are not currently logged into the server remotely, go ahead and log in. You should now be asked for a passphrase (which pertains to your password created above and not your system password).

Command line:
$ ssh -i /home/tc_user/.ssh/id_rsa tc_user@ssh_server_ip

Putty:
Under Connection -> SSH -> Auth specify the private key file and then login normally

In one more post we will look at a final program that can be used to take hardening the SSH service one step further.