So… you’ve just setup a shiny new server and you want to take measures to keep the bad guys out? Well, here I will give you a few tips on how to do just that.

This guide was written with CentOS 7.1 in mind but other up-to-date variants such as Fedora and RHEL should be pretty similar if not the same.

Hardening SSH (Secure Shell)

OpenSSH

Most of you will be using this protocol as a means to remotely administrate your Linux server and your right to. Using SSH is by far the best method to administer your server due to its use of encrypted communications unlike it’s older cousins rlogin and telnet which provide no secure methods of communication.

Create a standard user

Use the ‘useradd’ command to add a username of your choice.

useradd YOURUSER

Set a password for your newly created user.

passwd YOURUSER

Add your user to the WHEEL group to enable that user to use the sudo command.

usermod -aG wheel YOURUSER

Create an authentication key

RSA

This method of authenticating with your server is much more secure that using a standard password, part of this process will require you to create the key on your local machine which you will be connecting from.

You will be asked if you would like to protect the key with a password, I advise you to do this but it’s not mandatory.

Creating the key on Mac/Linux

ssh-keygen -b 4096

Press Enter to use the default names id_rsa and id_rsa.pub in /home/your_username/.ssh before entering your passphrase.

Upload your public key to your server

For Linux

ssh-copy-id YOURUSER@YOURSERVER

For Mac

On your server do.

sudo mkdir -p ~/.ssh && sudo chmod -R 700 ~/.ssh

From your Mac do the following making sure to substitute ‘youruser’ and ‘yourserver’.

scp ~/.ssh/id_rsa.pub YOURUSER@YOURSERVER.0:~/.ssh/authorized_keys

Now on to the configuration changes.

Open up the SSH config file for editing

In this section we will be performing the following actions

  • Disallowing root logins
  • Setting allowed users
  • Changing the default port
  • Disabling password authentication
  • Force protocol 2

You can replace nano with your favourite text editor such as vi.

sudo nano /etc/ssh/sshd_config

Disallow root logins.

Find the line that says

#PermitRootLogin yes

and change it to

PermitRootLogin no

Setting your user as an allowed user.

Add the following line to the bottom of your sshd_config file substituting ‘YOURUSER’ with your newly created account.

AllowUsers YOURUSER

Change the default service port.

Find the line that says

Port 22

Change to something other than 22 such as 22000

Port 22000

Disabling password authentication

We can disable password authentication because we will now be using our newly created key pair to authenticate to the server.

Look for the line that has

#PasswordAuthentication yes

and replace it with the below line.

PasswordAuthentication no

Only use SSH protocol 2

SSH Protocol 1 is generally considered obsolete as it’s vulnerable and old so lets go ahead and only use SSH Protocol 2. Protocol 2 should be enforced by default but it’s worth checking.

Look for the line that says.

#Protocol 2

Uncomment the line so it looks like this.

Protocol 2

There are many more options that we could set but this should be suffice in securing your SSH Service.

Save the file and restart the SSH service by doing the following.

sudo systemctl reload sshd.service

You should now be able to login on your chosen port with your authorised keys by connecting like this.

ssh YOURUSER@YOURSERVER -p 22000

Fail2ban

Fail2ban is a handy tool/service that monitors system log files to detect potential intrusion attempts and places bans using a variety of methods.

To install on CentOS we need to enable the EPEL repository by doing the following.

sudo yum install epel-release

Once the installation has completed we need to then go ahead and install Fail2ban

sudo yum install fail2ban fail2ban-systemd

Fail to ban comes with a wealth of options that would deserve a post all to itself so in this instance we will create a basic configuration file that will help secure your server, especially the SSH service.

Using SELinux? Then you will want to update your policy by doing the following.

yum update -y selinux-policy*

Configuration

We will be configuring fail2ban for use with Firewalld as it is implemented by default in CentOS 7.

Create a sshd.local file ready for editing.

sudo nano /etc/fail2ban/jail.d/sshd.local

Add the following lines.

[sshd]
enabled = true
port = 22000
logpath = %(sshd_log)s
maxretry = 3
bantime = 86400

Save the file and go ahead and start fail2ban.

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

You should now have a working fail2ban installation which will automatically ban IP addresses after 3 failed attempts at logging in to your system via SSH.

Apache Hardening

The default Apache configuration just works but there’s a few tweaks we can do here and there that makes the bad guys job a little harder. One of the things we can do is try and prevent information leakage.

By default Apache gives out server version information on error pages. We can prevent this by adding a couple of lines to our httpd.conf file.

Version banner

Open up the httpd config file ready for editing.

sudo nano /etc/httpd/conf/httpd.conf

add the following lines to the bottom of the file

ServerTokens Prod
ServerSignature Off

Cookies

Trace Requests

To protect yourself from Cross Site Tracing attacks append the following line to the end of your configuration file.

TraceEnable off

Set the HttpOnly and Secure flag

To mitigate against most of the common Cross Site Scripting (XSS) attacks you can set the following directive, again add the following line at the end of your configuration file.

Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

X-Frame Options

Adding this option to your configuration file will indicate whether or not a browser should be allowed to open a webpage in a frame or iframe. This will prevent site content embedded into other sites. See – https://www.owasp.org/index.php/Clickjacking.

Append the following line in your configuration file.

Header always append X-Frame-Options SAMEORIGIN

XSS Protection Again

To ensure and enforce web browser Cross Site Scripting protection append the following to your configuration file.

Header set X-XSS-Protection “1; mode=block”

Now with those options set we need to restart the Apache daemon.

sudo systemctl reload httpd.service

Logwatch

Now to keep tabs on all of those logs, Logwatch is a great tool to monitor your servers logs and email the administrator a digest on a daily basis.

Installation

sudo yum install logwatch sendmail

Now start sendmail.

sudo systemctl start sendmail

Configuration

The default configuration file for Logwatch is located at the below path.

/usr/share/logwatch/default.conf/logwatch.conf.

This file contains information on which directories for Logwatch to track, how the digest is sent and where the digest is sent to.

By default Logwatch keeps track of everything in /var/log but if you have other log files that you wish to add you can do this by adding the below to your logwatch.conf under the heading ‘Default Log Directory’.

LogDir = /some/path/to/your/logs

Email your daily digest

let’s go ahead and edit the logwatch.conf file.

sudo nano /usr/share/logwatch/default.conf/logwatch.conf

We need to change add your email into the configuration file so that the digest gets delivered to your inbox.

Look for the following section.

# Default person to mail reports to.  Can be a local account or a
# complete email address.  Variable Output should be set to mail, or
# --output mail should be passed on command line to enable mail feature.
MailTo = root

change ‘root’ to your own personal email address or wherever you want the digest sending to.

Adding Logwatch to Cron

Open up the crontab.

crontab -e

Now add the following line to the end of the file. This line will make logwatch run at midnight each day.

00 00  * * *          /usr/sbin/logwatch

This guide was a little quick and dirty so you have any additions to this guide I would love to hear them, also if you think something is wrong or could have been done more efficiently please get in contact.


James Smith

Security Researcher, Penetration Tester & Linux Advocate

17 Comments

Frank Breedijk · February 4, 2016 at 7:25 am

Ther is an error in your fail2ban ssh setup. You are telling it to block the standard ssh port when there are to many failures, but you are not running ssh on the standard ssh port.

    smittix · February 4, 2016 at 7:54 am

    Hey Frank, thanks for that will change accordingly. Good spot!

    Smittix · February 5, 2016 at 8:56 am

    Hi Thanks for reaching out. It looks as if when choosing the service SSH it will work the same as putting the port in due to settings in sshd_config. I tested this, even though my ssh service was on a non default port.

John · July 9, 2017 at 12:42 am

Really good tutorial, I’m using this now.

    smittix · July 10, 2017 at 7:31 am

    Hi John, Thanks for the feedback. Great to see it’s coming in handy for yourself.

      John · July 10, 2017 at 9:55 am

      Where I come to change the Port number, there’s a note saying:

      # If you want to change the port on a SELinux system, you have to tell
      # SELinux about this change.
      # semanage port -a -t ssh_port_t -p tcp #PORTNUMBER

      If this is necessary, maybe it’s worth popping it in the tutorial?

        smittix · July 10, 2017 at 10:05 am

        Strange, This must be an SELinux change that has happened. I will double check and add it into the guide. Thanks for pointing that out.

      John · July 10, 2017 at 10:04 am

      One more thing, making the port number adjustment results in Job for sshd.service invalid. when trying to restart the service. Any ideas?

        smittix · July 10, 2017 at 10:10 am

        Have you made the change to the config file before issuing the SELinux command?

          John · July 12, 2017 at 6:34 pm

          Ended up asking my server support to do it – no idea what they did.

John · July 12, 2017 at 6:50 pm

Still loving the tutorial.

Header set X-XSS-Protection “1; mode=block”

Uses curly quotes! Please change them to “”s.

Also, there’s a CIS Linux server benchmark for people interested in taking their security to the next level.

    Smittix · July 18, 2017 at 9:33 am

    Hey John, not noticed that before. As you can see from your reply it changes normal quotes to curly ones. Must be a wordpress theme thing. I will check it out.

John · July 17, 2017 at 6:14 am

Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

Breaks Drupal logins on http (presumably WordPress logins too, btw.

www.lisenet.com · September 20, 2017 at 11:27 am

I’d suggest adding the following Apache headers too since they became a standard nowadays:

X-Content-Type-Options
Content-Security-Policy
Strict-Transport-Security

Also, if you change the default SSH port, you need to tell SELinux about it (I take it that you have it set to the enforcing mode since you are hardening the server) as it won’t work otherwise.

Lew Payne · November 12, 2017 at 4:29 pm

James – I have additional hardening steps for sshd (both as client and server). The steps limit the available protocol negotiations to only those that are NIST/HIPAA approved. In the real world, I’ve found this to foil current scan bots, which attempt to negotiate with a weaker set of protocols. I will pass these things and onto you via email, if you want.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: