Securing your OpenSSH server in Linux

Secure Shell (SSH) is a program used to secure communication between two entities, often used as a replacement for Telnet and the Berkeley protocols such as remote shell (RSH) and remote login (Rlogin). SSH is also used as a secure remote copy utility, replacing traditional protocols such as the File Transfer Protocol (FTP) and Remote Copy Protocol (RCP).

For this tutorial, we are going to demonstrate steps on securing your OpenSSH which is a free version of the SSH protocol suite.

Note: Steps 1-9 can be done by  tweaking your sshd_config and do ssh service restart after changes to take effect.

1. Use SSH Protocol 2
Use SSH version 2 (SSH2) only as it offers more performance, flexibility and security than SSH1.
-To verify what SSH protocol version you are running, check your /etc/ssh/sshd_config and look for the line “Protocol”,

[[email protected] ~]# vi /etc/ssh/sshd_config

Protocol 2

[[email protected] ~]# /etc/init.d/sshd restart
Stopping sshd: [  OK  ]
Starting sshd: [  OK  ]

2. Disable direct root SSH logins
-disable direct logging in as root via ssh. This is like inviting hackers to brute force your root password.
It’s recommend to login as a normal user and then after that, just use su or sudo if want to execute priviledge commands.

PermitRootLogin no

3. Enable a SSH warning banner
You can display a warning banner before login to require acknowledgment of the contents. This can be done by defining under sshd_config

a. Create a Banner on any location. e.g. /etc/freelinux

[[email protected]~]# vi /etc/freelinux
###############################################################
AUTHORIZED USERS ONLY
All login attempts will be logged!!!
###############################################################

b. Edit /etc/ssh/sshd_config. Locate the line containing “Banner”, uncomment and specify the file location
vi /etc/ssh/sshd_config

# no default banner path

Banner /etc/freelinux

c. Restart ssh service

[[email protected]~]# service sshd restart
Stopping sshd: [  OK  ]
Starting sshd: [  OK  ]

d. Test:
@ssh client
login as: darwin
###############################################################
AUTHORIZED USERS ONLY
All login attempts will be logged!!!
###############################################################
[email protected] password:
Last login: Fri Oct 19 18:19:12 2012 from 10.0.2.2

4. Disable empty passwords
To disable empty password, edit /etc/ssh/sshd_config and make sure this line below is uncommented

PermitEmptyPasswords no

5. Disable Host-based authentication
It is not recommended that hosts always agreed to trust one another

HostbasedAuthentication no

6. Configure Idle Timeout
Let say you want the system to log out users after 15 mins of idling. Then you can set this:

[[email protected]~]# vi /etc/ssh/sshd_config

ClientAliveInterval 300
ClientAliveCountMax 3

where:

This will give a timeout of 15 minutes (300 secs X 3)
ClientAliveInterval – timeout in seconds.
ClientAliveCountMax – total number of checkalive message sent by the ssh server without getting any response from the ssh client

Also,  you can do this 15 minute timeout:
ClientAliveInterval 900
ClientAliveCountMax 0

Additional Tip: This is slightly different with “TMOUT” variable that will terminate the shell if no activity for N seconds
# export TMOUT=N

[[email protected]~]# export TMOUT=60

7. Limit SSH LoginGraceTime
By default, sshd will allow a connected user that has not begun the authentication process for a period 2 minutes (120 secs) for a grace time. It’s recommended to shorten this time to protect from brute force attacks.

LoginGraceTime 30

8. Change ssh port number
The advantage of this is somehow protects your box against automated attacks or malicious scripts that is trying to get in via ssh default port 22.

Port 35286

9. Limit or Permit only specific users or groups to login
All users by default is allowed to access your box. But you have the options to allow or deny few users or groups. This can be done in either of this way.

#[AllowUsers]

AllowUsers darwin tux

OR

#[DenyUsers]

DenyUsers user1 user2
DenyGroups group1 group2 group3

10. Update OpenSSH & OS
Make sure your Linux system is running the latest version for OpenSSH. SSH package version depends on your Linux distribution & OS version. Your distro will use the best or stable version for any packages, so if you want to upgrade to another version, you can do this via source package installation. It can be downloaded on OpenSSH official site http://www.openssh.com. Alternatively, you can do it by installing the latest rpm package or changing your repository, then use the yum.

For instance, if you are running CentOS 5.8 to check the current installed package and verify if there’s update, tr the following:

[[email protected]~]# cat /etc/issue
CentOS release 5.8 (Final)
Kernel r on an m

[[email protected]~]# rpm -qa | grep openssh
openssh-4.3p2-82.el5
openssh-clients-4.3p2-82.el5
openssh-server-4.3p2-82.el5

[[email protected]~]# ssh -V
OpenSSH_4.3p2, OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008

[[email protected]~]# yum update openssh*
Loaded plugins: fastestmirror, security
Determining fastest mirrors
* base: mirror.nus.edu.sg
* extras: mirror.nus.edu.sg
* updates: mirror.nus.edu.sg
base                                                     | 1.1 kB     00:00
extras                                                   | 1.9 kB     00:00
extras/primary_db                                        | 171 kB     00:00
updates                                                  | 1.9 kB     00:00
updates/primary_db                                       | 828 kB     00:01
Skipping security plugin, no data
Setting up Update Process
No Packages marked for Update

11. Enforce access controls list by using TCP wrappers
TCP wrappers is used to restrict access to TCP services based on IP, hostname, network address etc. It supports SSH via the libwrap library. To check if your sshd is

dynamically linked against libwrap:

[[email protected]~]# which sshd
/usr/sbin/sshd
[[email protected]~]# ldd /usr/sbin/sshd | grep libwrap
libwrap.so.0 => /lib/libwrap.so.0 (0×00978000)

@/etc/syslog.conf
# The authpriv file has restricted access.
authpriv.*                                              /var/log/secure

Configuration Files of TCP Wrapper

a. /etc/hosts.allow
b. /etc/hosts.deny

The file names are quite self-explanatory.
Access will be allowed when it matches an entry in the /etc/hosts.allow file
Access will be denied when it matches an entry in the /etc/hosts.deny file

But take note of the rules or points to consider
– access rules in hosts.allow are applied first
– rules in each file are read from the top down, so take note the order of rules
– changes in hosts.allow or hosts.deny will take effect immediately, no need to restart any services.
– access to service is permitted if no rules are found in either file
– use ‘#’ character to insert comments
– it uses this format

tcp_service : client_list [ : shell_command ]

where:
tcp_server – daemon process names
client_list – IP, hostnames, patterns, wildcards matching the client address or hostname

There are several patterns that you can use under client_list which we will not covering on this topic. But the recommended setting will be:
Deny anything not explicitly allowed and only Allow certain services.

[[email protected]~]# cat /etc/hosts.allow
#
# hosts.allow   This file describes the names of the hosts which are
#               allowed to use the local INET services, as decided
#               by the ‘/usr/sbin/tcpd’ server.
#
ALL: ALL

[[email protected]~]# cat /etc/hosts.allow
#
# hosts.allow   This file describes the names of the hosts which are
#               allowed to use the local INET services, as decided
#               by the ‘/usr/sbin/tcpd’ server.
#
sshd : freelinuxtutorials.com : allow
sshd: 192.168.0.192/255.255.255.240 : allow
sshd : 192.168.0.100 : allow

12. Configure iptables for added SSH security
It’s good to have your servers protected by hardwares or appliances such as security appliances, PIX, ASA etc. that will added more protection such as limiting TCP connections esp. on preventing dictionary attacks.
If you don’t have this, it’s a good thing this can be done also from your Linux server using iptables.

Sample iptables  to allow only specified host:
iptables -A INPUT -p tcp -m state –state NEW –source 172.16.0.101 –dport 35286 -j ACCEPT

Another example iptables rule:

iptables -N RULE1
iptables -A INPUT -p tcp –dport 35286 -m state –state NEW -j RULE1
iptables -A RULE1 -m recent –set –name SSH
iptables -A RULE1 -m recent –update –seconds 60 –hitcount 4 –name SSH -j DROP

where:
Line1: create a new chaing RULE1
Line2/3: allow incoming SSH connection on ssh port 35286 and it will pass through this chain
Line4: source IP should not be more than 3 attempts within 60 seconds, else packets will be dropped from that source IP

13.  Use Strong Passwords
As system administrator, you can set a criteria for users to have a strong passwords. To enforce password complexity on  your Linux boxes via  PAM (the “pluggable authentication module”)

[[email protected]~]# cat /etc/pam.d/system-auth | grep password
password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

Change to something like this:
password requisite pam_cracklib.so try_first_pass retry=3 minlength=12 lcredit=1 ucredit=1 dcredit=1 ocredit=1 difok=4

where:

try_first_pass = sets the number of times a user can attempt to set a good password before it aborts
minlen = measure of complexity related to the password length
lcredit = minimum number of required lowercase letters
ucredit = minimum number of required uppercase letters
dcredit = minimum number of required digits
ocredit = minimum number of required other characters
difok = sets the number of characters that must be different from the previous passwords

Alternatively, you can use /etc/login.defs to set parameters such as password expiration, etc.
@/etc/login.defs

# Password aging controls:
#
#       PASS_MAX_DAYS   Maximum number of days a password may be used.
#       PASS_MIN_DAYS   Minimum number of days allowed between password changes.
#       PASS_MIN_LEN    Minimum acceptable password length.
#       PASS_WARN_AGE   Number of days warning given before a password expires.
#
PASS_MAX_DAYS   99999
PASS_MIN_DAYS   0
PASS_MIN_LEN    5

14. Use Private/Public Keys for SSH authentication
If you decided not to do password authenticaton instead using of keys, then you can follow this tutorial.

15. Patch OpenSSH to latest security fix
As long as you have the latest updates or patches installed on your Linux distribution, that should be enough to tell that you are fully patched.
To check the changelog for the openssh rpm, use the command below. It will show you various patches

[[email protected]~]# rpm -q –changelog openssh | more