How to secure the SSHD daemon?

Solution Verified - Updated

Environment

  • Red Hat Enterprise Linux (RHEL)

Issue

  • Some system administrators noticed that attackers have been attempting to login with common usernames and passwords over SSH. In the system logs of /var/log/secure, similar entries to the following for many common usernames (such as "admin", "guest", "test", and "root") may be seen:
        Oct 28 11:11:08 hostname sshd[13412]: Illegal user admin from 172.16.59.10
        Oct 28 11:11:12 hostname sshd[13412]: Failed password for illegal user admin from 172.16.59.10 port 33762 ssh2
  • Repeated attempts may be indicative of an attacker trying to guess the password to a particular account, especially the root account, by "brute force". A brute force attack is one where the password is repeatedly guessed until the correct one is found.

Resolution

There are many ways to make SSH more secure. Here we discuss some guidelines.

Using TCP Wrappers

The most simple way to secure the SSH daemon is to selectively deny access to it using features from the tcp_wrappers-libs package. This package is installed by default.

tcpwrappers are configured through the files /etc/hosts.allow and /etc/hosts.deny. To completely deny access to the SSH daemon, add the following text to /etc/hosts.deny:

    sshd: ALL

This will completely disable access to the SSH daemon from any client. If there are a few hosts that should be allowed to connect, add the following lines to /etc/hosts.allow:

    sshd: 192.168.0.1, trusted.one-domain.com, 192.168.23.0/24, *.trusted.net

This would allow connections from the IP address 192.168.0.1, the hostname trusted.one-domain.com, the network 192.168.23.0/24, and the domain *.trusted.net while disallowing any other connections.
Remember, you need to deny and allow host/networks.

Using iptables

When you have a host within the local corporate network use TCP Wrappers is probably enough since most of the hosts are under your control, so you can ensure a low chance of attack. But What happen if you have a SSHD Service running over internet, or on a non-administered (Hostile) network like a site2site vpn with a provider? You can get more control on access with iptables. Also iptables can give to you more flexibility and robustness.
You can list your rule set with the iptables -nL --line-numbers command to see what rules are in place already, this is the default rules that came with the fresh Red Hat 6.5 Install:

    # iptables -nL --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
2    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           
3    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22 
5    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited 

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited 

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Then you can add or remove the rules. The next examples on the INPUT chain will insert a rule to iptables at position.
Remember that you need to put the rule on a specific position, ie. line 3, just over the default DROP rules, you can specify it writing:

    # iptables -I INPUT 3 -p TCP -i eth0 -s 192.168.1.39 --dport 22 -j ACCEPT

Running the following command as root will drop all SSH access to 192.168.1.22:

    # iptables -I INPUT <line-number> -p tcp -i eth0 -s 192.168.1.22 --dport 22 -j DROP

Please refer to man iptables for additional options and usage, or autohelp iptables --help for a short summary:

If you want to enable some specific host, you can run the following command to allow the access:

    # iptables -I INPUT <line-number> -p tcp -i eth0 -s 192.168.1.39 --dport 22 -j ACCEPT

Additionally, one of the best use of a firewall in case of the SSH service on an insecure network is to apply rate-control over the non-secure origins; to do it, you just need to use:

    # iptables -I INPUT <line-number> -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH 
    # iptables -I INPUT <line-number> -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 12 --rttl --name SSH -j LOG --log-prefix 'SSH-HIT-RATE: '
    # iptables -I INPUT <line-number> -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 12 --rttl --name SSH -j DROP
    # iptables -I INPUT <line-number> -p tcp --dport 22 -m state --state NEW -j ACCEPT # on the default fresh-install ruleset this rule is already in place, you can ignore

These 3 rules setup a hitrate of 12 new connection tries by minute, you need to adjust this values according to your needs. All the logs of this rule will appear in the /var/log/messages file, prefix 'SSH-HIT-RATE' is used to ease looking for the related entries.

Please take special attention when you test your new rules. If you make a non-critical mistake, you can go back to the previous saved config using service iptables force-reload. When the configuration was finalized, you can save your firewall rules with service iptables save.

Using /etc/ssh/sshd_config

There are other steps that can be taken if restricting access is not possible. This is some of the best practices of the SSHD configuration:

  • The most highly recommended action, especially as a defense against brute force attacks, would be to prevent root from logging in directly via SSH. To do this you need change the line which reads:
    #PermitRootLogin yes

to the following:

    PermitRootLogin no

This will require that you configure sudo or use su to gain privilege as the user root over the ssh session of a non-root user. Alternatively, you can set up ssh keys for the user root and use

    PermitRootLogin without-password

to allow the user root to log in using keys only.

  • Change the specific port other than the default. It is possible to change it to any random number between 1025 and 65535, as attackers will assume that port 22 will be used for the ssh protocol. Find this line in /etc/sshd/sshd_config:
    #Port 22

Change it to something like this:

    Port 1101

Port number 1101 is an example. Now you need to access to this server to the port 1101 when you do a ssh connection:

$ ssh someuser@ssh-server:1101
  • Ensure that the server only accept the SSH Protocol Version 2:
# Protocol 2,1
Protocol 2
  • Change the time that a user can spend with the login prompt open (value in seconds):
# Default value is 120 seconds.
# Adjust this value according your needs.
LoginGraceTime 30

This cuts down some kind of DoS attacks that can be done simulating slow logins.

  • To further mitigate DoS Attacks that use Bruteforce login attems you can use the MaxStartups value, this value specifies the maximum number of concurrent unauthenticated connections. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection. But, the most usefull feature of this option becames when you use a three value alternative, this enable the "Random Early Drop" the three value is specified separated by a colon: start:rate:full, ie: 5:30:25, with this values the SSHD will refuse connection attempts with a probability of “rate/100” (30%) if there are currently “start” (5) simultaneous unauthenticated connections. The probability increases linearly and all connection attempts are refused if the number of unauthenticated connections reaches “full” (25).
MaxStartups 5:30:25 #This values are usefull for a low use sshd server, mostly used for administrative access.

This not apply a limit for concurrent connection, only limit the simultaneous login attempts.

  • Further security can be gained by requiring that all logins use public/private key pairs to log in, instead of a password. Note that this requires that every user set up a public/private key pair prior to the changes being made to the configuration file. It will also prevent newly created users from logging in via SSH if a public/private key pair is not created and given to them by the system administrator. To make this configuration please follow this link:

How to setup SSH passwordless login

  • To block access to hosts attempting to brute force attack the system, these additional 3rd party packages services can be used:

    • fail2ban (EPEL)
    • denyhosts (EPEL)
    • sshguard
    • sentry

They operate on different layers, providing different approach to act on a specific event.

If you need to setup the keys on a windows putty client please follow this:

How to use ssh keys with putty and Red Hat Enterprise Linux?

SBR
Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.