The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

[Tutorial] Interested in increasing the security of your server? Read this. (sshd hardening)

Discussion in 'Security' started by JeffP., Apr 16, 2014.

  1. JeffP.

    JeffP. Well-Known Member

    Sep 28, 2010
    Likes Received:
    Trophy Points:
    This topic applies to the OpenSSH software in particular, which is distributed with Redhat and CentOS Linux.


    • ability to log into the shell via ssh
    • ability to work from the command line to edit files, restart services


    What is ssh?

    ssh stands for Secure Shell, and is primarily used for acquiring interactive shell access on servers. Data transmitted via ssh is encrypted. This protects sensitive information from eavesdropping, such as the transmission of your username and password information upon logging in, and commands issued throughout the duration of your session. Secure Shell supercedes older protocols such as telnet, which sent information over the network unencrypted.

    With shell access, users and system administrators can run a wide variety of commands. This makes the sshd service a prime target of spammers, bots, and the like.

    By default, sshd:

    • does not restrict which IP addresses can connect to it
    • does not restrict which users can authenticate (including the root user)
    • uses password authentication instead of public key auth

    This means that:

    • vulnerabilities in sshd could allow someone to remotely gain access to your server by exploiting a bug in the software
    • brute force attempts against sshd could allow someone to gain access to your server through a weak password
    • aggressive, prolonged brute force attempts against sshd can cause server stability issues

    This tutorial will explore preventive measures that can be put in place by the server admistrator for the purpose of mitigating these issues.

    All that is required is the ability to issue very basic commands, such as editing a file. Additionally, each of these measures should be applied. Selecting only a few is not as beneficial as applying each.

    Managing shell access

    You can restrict who can log into the shell via WHM >> Manage Shell Access. Information on this feature can be found here:

    NOTE: This does NOT restrict who can invoke the shell to execute commands. This restricts who can authenticate to the shell, such as via sshd. Shell commands may still be executed without logging into the shell, such as via PHP, perl, Ruby, Python, cron jobs, and so on.

    If a user does not need interactive shell access, it is recommended to set their shell to "Disabled Shell". If you want to give a user shell access in a restricted environment, use "Jailed Shell". Using a jailed shell restricts access to certain commands by default, which directories a user can access, and more. This is the recommended option to use if shell access for a user is necessary.

    You can disable shell access for new accounts prior to their creation by disabling the "Shell Access" option in the package that the account uses. See the "Packages" section in WHM.


    Changing the sshd port

    While not a security measure, changing the port that sshd listens on can provide a few benefits. For one, it requires more effort for someone to locate the port that sshd listens on. Secondly, it prevents the server from being overwhelmed by brute force attacks that rely on using the default sshd port of 22. Both of these things can be prevented by filtering access, but this is still helpful in cases where the filter is either not enabled, or misapplied.

    Keep in mind that local users can use utilities such as "ss" or "netstat" or other means to determine which ports that services listen on.

    NOTE: Anyone on the server can bind to ports 1024 and above. Only root can bind to ports below 1024. As such, it is imperative to use an available port below 1024.

    To find a free port, start by looking for used ports:

    # netstat -ntl | awk '{print $4}' | grep -v ^ | cut -d : -f 2 | grep ^[0-9] | sort -n | uniq | awk '$1 < 1024'
    The command works as follows:

    netstat -ntl        : show listening (-l) TCP (-t) ports, and do not convert port numbers into service names (-n)
    awk '{print $4}'    : display the 4th field of output
    grep -v ^ : do not display information about the loopback IP address ( in the output
    cut -d : -f 2       : using ':' as the delimiter, print the second field of output
    grep ^[0-9]         : show only lines that begin (^) with the numbers 0 through 9
    sort -n             : sort the output numerically
    uniq                : do not display duplicate lines
    awk '$1 < 1024'     : print only numbers that are less than 1024
    All of these commands have man pages that explain their usage.

    The following is a list of commonly used ports. These should not be used since they are used by other services:

      21 (ftp)
      22 (ssh)
      25 (smtp)
      26 (alternate smtp port)
      53 (dns)
      80 (http)
    110 (pop)
    143 (imap)
    443 (ssl)
    465 (smtps)
    587 (smtp)
    993 (imaps)
    995 (pop3s)
    Any other unused port below 1024 is fine.

    Restrict host access

    There are various ways in which access can be restricted to sshd. By restricting which users and hosts/networks that can log in, the impact of stolen credentials may be minimized.

    You can restrict which hosts/networks can access sshd via proper firewalling. Linux provides firewall software called "iptables". What follows is an example of allowing just 1 particular IPv4 address to connect to sshd while denying all others:

    # iptables -I INPUT -p tcp -s --dport 22 -j ACCEPT
    # iptables -A INPUT -p tcp --dport 22 -j DROP
    An explanation of the first command is as follows:

    iptables    : this is the iptables utility
    -I          : insert a rule...
    INPUT       : ...into the INPUT table
    -p          : specify the protcol...
    tcp         : the TCP protocol
    -s          : specify the source IP address...     :
    --dport     : specify the destination port...
    22          : 22
    -j          : jump to...
    ACCEPT      : the ACCEPT target
    An explanation of the second command is as follows:

    iptables    : this is the iptables utility
    -A          : append a rule...
    INPUT       : the INPUT table
    -p          : specify the protcol...
    tcp         : the TCP protocol
    --dport     : specify the destination port...
    22          : 22
    -j          : jump to...
    DROP        : ...the DROP target
    In order to make the rules persist across reboots, the ruleset must be saved:

    # service iptables save
    An explanation of the command is as follows:

    service     : this is the "service" command
    iptables    : this is the "iptables" service
    save        : this saves the current state of the iptables service
    Restrict root access

    By default, root can log into the shell. It is a very common practice to log into the shell directly as root, but is a very bad idea to do so for the following reasons:

    • If sshd is trojaned to record usernames and passwords, your root password has now been compromised (though it could be trivially compromised in other ways)
    • If sshd is logged into from a hacked machine that is recording credentials, your root password has now been compromised

    The first example is very common. Imagine this scenario: a remote attacker exploits a vulnerability in a user's PHP script (e.g., a popular CMS, or a WordPress plugin). Then they upload a kernel or other exploit to the server and execute it, which provides them with root access.

    Now root access has been obtained, but the attacker still does not know the server's root password, or the passwords of any other accounts for that matter. There are a number of ways in which that information could be obtained, and a popular method is to replace the existing ssh daemon with one that records the username and password information of users as they log in. This information is especially useful to an attacker when passwords are reused, which will be discussed in further detail later.

    Preventing the root user from logging in can be done by setting this line in /etc/ssh/sshd_config:

    PermitRootLogin no
    then restarting the sshd service.

    NOTE: Before doing this, be sure that you have an account that can obtain root access (such as via su or sudo).

    Restrict user access

    Another method that can be used to restrict logins via sshd is with the "AllowUsers" option in /etc/ssh/sshd_config . This option allows you to specify a list of users that can log into the shell. Only these users will be able to log in, and no one else.

    To permit only the user "alice", you'll need to edit /etc/ssh/sshd_config and add the following line:

    AllowUsers alice
    then restart sshd.

    NOTE: Before doing this, be sure that the alice account can obtain root access (such as via su or sudo) if it will be the account you intend to use for escalating to root.


    Before we discuss using ssh keys instead of passwords, let's cover why password authentication contains inherent weaknesses.

    Password reuse

    This is the practice of using the same password for more than one resource, such as having 5 servers with the same root password. This is temporarily convenient for admins, but potentially devastating if someone obtains the password for just one of the servers.

    Do not use the same password for any account - not just root. All passwords should be unique, and never used again after being changed. Consider the potential consequences if your root password is the same as that of your Gmail account, or bank, etc.

    Use a "password safe" type of application. This allows you to store all of your passwords in a central location, which you only need 1 password to access. A Google search will provide a number of results for freely available password safe software, including Password Safe, KeePass, and ccrypt.

    Poor passwords

    Poor passwords greatly contribute to compromised accounts and compromised servers. Poor passwords are those which can be guessed easily, or brute forced in a reasonable amount of time. Every botnet in existence that attempts to brute force sshd is going to try the password "123456". Inevitably, some users on your server(s) will use (or try to use) that and other equally poor password choices.

    You can prevent users from using poor passwords for a number of services via WHM >> Password Strength Configuration.

    This feature is documented here:

    Use ssh keys instead of password auth

    1) On the machine that you want to ssh from, generate a keypair:

    $ ssh-keygen -t rsa -b 4096
    That command will generate an ssh key of type (-t) "rsa" with a block size of 4096 bits (-b).

    This will prompt you to enter a name for the key, otherwise .ssh/id_rsa will be used by default. It will also prompt you to enter a password. Enter a very strong password.

    This is a very good password: 6!o:0Q_C-=A]-!Q0,kh%RAC(h<ys:;/xnv}WDknsxOy5{}$Wdn
    This is not: superman

    You should now have a keypair:

    ~/.ssh/ = public key
    ~/.ssh/id_rsa     = private key
    2) On the server that you want to ssh into, create a file at ~/.ssh/authorized_keys and place the contents of inside. You may need to create the ~/.ssh directory first. Give it permissions of 0700. Give the permissions of the authorized_keys file 0600.

    Now attempt to log into the server via the ssh key. On the server that you want to ssh from:

    $ ssh -i ~/.ssh/id_rsa
    You should be prompted to enter the password for the key, and then be logged into the shell.

    If that works, and your user has the ability to obtain root access via su or sudo, you can now disable password authentication for sshd:

    1. Log into WHM as root
    2. Click "SSH Password Authorization Tweak"
    3. Click "Disable Password Auth"

    NOTE: If you accidentally misconfigure your SSH configuration file, you can access the following link to run a script on your server:

    This script will temporarily configure an additional SSH configuration file for port 23, allowing you to access, edit, and fix the original SSH configuration file. Replace "" with the hostname or IP address of your server.


    Recommended settings for sshd_config

    PermitRootLogin no          # disallow direct root logins
    PasswordAuthentication no   # disallow password auth (use ssh keys instead)
    AllowUsers alice            # deny all users by default, permit by exception
    Port 75                     # an unused port that is < 1024. access to this port should be restricted
    ListenAddress x.x.x.x       # by default, sshd listens on all IPv4 and IPv6 interfaces. limit which interface is used with the LimitAddress directive
    sshd best practices summary

    • deny all, permit by exception (iptables or tcpwrappers, AllowUsers)
    • never log into sshd as root (PermitRootLogin no)
    • use strongly passworded ssh keys instead of password auth (PasswordAuthentication no)
    • remove temporary accounts, such as those used by 3rd party support companies
    • change any passwords used by 3rd party support users
    • never reuse passwords
    • rotate passwords periodically, if you use them
    • rotate ssh keys periodically
    • use WHM >> Configure Security Policies
    • configure a remote syslog server. that way if you do get hacked, you still have logs safely stored at another location

    Questions? Comments? Corrections? Let us know your thoughts!
  2. georgeb

    georgeb Well-Known Member

    May 23, 2010
    Likes Received:
    Trophy Points:
    Montreal, QC, Canada
    cPanel Access Level:
    Root Administrator
    I am more paranoid than you are and make the sshd_config file write protect and check any user IP (at the login time, just in case that somebody hacked in) and lock down the server if the Ip if is not for my list. But this is just me :)
  3. penguinbliss

    penguinbliss Member

    Jul 3, 2012
    Likes Received:
    Trophy Points:
    cPanel Access Level:
    Root Administrator
    Hey jeff, thanks very much man for the wonderful post :)
  4. mywhm

    mywhm Active Member

    Jan 15, 2014
    Likes Received:
    Trophy Points:
    cPanel Access Level:
    Root Administrator
    Hi there, thanks for the tutorial.

    About this:

    I think the explanation relation to INPUT (into the INPUT table )
    is unclear, should be:

    INPUT = is a chain or rule handles all packets that are addressed to your server - incoming traffic

    filter: This is the default table (if no -t option is passed)

Share This Page