Security hardening on Amazon Linux, CentOS 6 and Red Hat 6

A few years ago I wrote a quite popular post for security hardening on Ubuntu 14.04, and since I’ve just had to do a similar series of operations on Amazon Linux I thought I’d update the post accordingly. This should also apply to CentOS 6 and Red Hat 6, since those are very similar distributions to Amazon Linux.

Assume that all these operations need to be performed as root, which you can do by logging in as root with sudo -i (or you can issue an endless series of sudo commands if you prefer).

Harden SSH

I generally regard it as a sensible idea to disable root login over SSH, so in /etc/ssh/sshd_config you could change PermitRootLogin to no. The default nowadays seems to be forced-commands-only which is probably an acceptable compromise, so you could probably leave it like that without worrying further.

If SSH on your servers is open to the world then I also advise running SSH on a non-standard port in order to avoid incoming SSH hacking attempts. To do that, in /etc/ssh/sshd_config change Port from 22 to another port of your choice, e.g. 1022. Note that you’ll need to update your firewall or EC2 security rules accordingly.

After making changes to SSH, reload the OpenSSH server:

service sshd reload

Improve IP security

Add the following lines to /etc/sysctl.d/10-network-security.conf to improve IP security:

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0 
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Ignore send redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Block SYN attacks
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# Log Martians
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0 
net.ipv6.conf.default.accept_redirects = 0

# Ignore Directed pings
net.ipv4.icmp_echo_ignore_all = 1

Load the new rules:

sysctl --system

PHP hardening

If you’re using PHP, these are changes worth making in /etc/php.ini in order to improve the security of PHP:

  1. Add exec, system, shell_exec, and passthru to disable_functions.
  2. Change expose_php to Off.
  3. Ensure that display_errors, track_errors and html_errors are set to Off.

Apache hardening

If you’re using Apache web server, it’s worth making sure you have the following parameters set in the config to make sure Apache is suitably hardened:

ServerTokens Prod
ServerSignature Off
TraceEnable Off
Header unset ETag
FileETag None

You may find TraceEnable Off already set in /etc/httpd/conf.d/notrace.conf. I find the simplest thing is to place whichever of these parameters are not already set into a new file /etc/httpd/conf.d/security.conf.

Then restart Apache:

service httpd restart

Install and configure ModSecurity

If you’re using Apache, the web application firewall ModSecurity is a great way to harden your web server so that it’s much less vulnerable to probes and attacks. Firstly, install the necessary packages:

yum install mod24_security

(That’s if you’re using Apache 2.4, otherwise it’s probably just yum install mod_security)

Next, install the Open Web Application Security Project ModSecurity Core Rule Set:

cd /tmp
cp -r owasp-modsecurity-crs-3.3-dev /etc/httpd
mv /etc/httpd/owasp-modsecurity-crs-3.3-dev/crs-setup.conf.example /etc/httpd/owasp-modsecurity-crs-3.3-dev/crs-setup.conf

To add the rules to Apache, edit /etc/httpd/conf.d/mod_security.conf and add the following lines near the end, just before </IfModule>:

Include owasp-modsecurity-crs-3.3-dev/crs-setup.conf
Include owasp-modsecurity-crs-3.3-dev/rules/*.conf

Restart Apache to activate the new security rules:

service httpd restart

Install and configure mod_evasive

If you’re using Apache then it’s a good idea to install mod_evasive to help protect against denial of service attacks. For Apache 2.4 there’s no package available so we need to do it using apxs. (If you’re using Apache 2.2 then you should be able to install with yum, or you can do it this way but change the module name accordingly for the Apache version you’re using.) You may firstly need to install relevant development tools:

yum install httpd24-devel
yum groupinstall "Development Tools"

Then grab mod_evasive and install:

cd /tmp
wget -c
cd mod_evasive-master
apxs -i -a -c mod_evasive24.c

I would then comment out this line in /etc/httpd/httpd.conf:

LoadModule evasive20_module /usr/lib64/httpd/modules/

Then create /etc/httpd.d/mod_evasive.conf and put all the relevant bits in there:

LoadModule evasive20_module   /usr/lib64/httpd/modules/

    DOSHashTableSize    3097
    DOSPageCount        5
    DOSSiteCount        50
    DOSPageInterval     1
    DOSSiteInterval     1
    DOSBlockingPeriod   10
    DOSEmailNotify      root

Restart Apache to activate it:

service httpd restart

Install and configure rootkit checkers

It’s highly desirable to get alerted if any rootkits are found on your server, so let’s install a couple of rootkit checkers:

yum install rkhunter chkrootkit

Let’s run rkhunter weekly instead of daily, because daily is too annoying:

mv /etc/cron.daily/rkhunter /etc/cron.weekly

We also need to add a weekly cronjob for chkrootkit:

echo "5 5 * * Sun root /usr/sbin/chkrootkit" > /etc/cron.d/chkrootkit

Install Logwatch

Logwatch is a great tool which provides regular reports nicely summarising what’s been going on in the server logs. Install it like this:

yum install logwatch

Make it run weekly instead of daily, otherwise it gets too annoying:

mv /etc/cron.daily/0logwatch /etc/cron.weekly

Make it show output from the last week by editing /etc/cron.weekly/0logwatch and adding --range 'between -7 days and -1 days' to the end of the logwatch command (so that it says logwatch --range 'between -7 days and -1 days').

Enable process accounting

Linux process accounting keeps track of all sorts of details about which commands have been run on the server, who ran them, when, etc. It’s a very sensible thing to enable on a server where security is a priority, so let’s activate it:

chkconfig psacct on
service psacct start

To show users’ connect times, run ac. To show information about commands previously run by users, run sa. To see the last commands run, run lastcomm. Those are a few commands to give you an idea of what’s possible; just read the manpages to get more details if you need to.

I threw together a quick Bash script to send a weekly email with a summary of user activity, login information and commands run. To get the same report yourself, create a file called /etc/cron.weekly/pacct-report containing the following (don’t forget to make this file executable) (you can grab this from GitHub if you prefer):


echo ""

ac -d -p

echo ""
echo ""

users=$(cat /etc/passwd | awk -F ':' '{print $1}' | sort)

for user in $users ; do
  comm=$(lastcomm --user $user | awk '{print $1}' | sort | uniq -c | sort -nr)
  if [ "$comm" ] ; then
    echo "$user:"
    echo "$comm"

echo ""
echo ""

sa | awk '{print $1, $5}' | sort -n | head -n -1 | sort -nr

Things I haven’t covered

There are some additional issues you might want to consider which I haven’t covered here for various reasons:

  1. This guide assumes your server is on a network behind a firewall of some kind, whether that’s a hardware firewall of your own, EC2 security rules on Amazon Web Services, or whatever; and that the firewall is properly configured to only allow through the necessary traffic. However, if that’s not the case then you’ll need to install and configure a firewall on the server itself. The recommended software for this would probably be iptables.
  2. If you’re running an SSH server then you’re often told that you must install a tool such as fail2ban immediately if you don’t want your server to be hacked to death within seconds. However, I’ve maintained servers with publicly-accessible SSH servers for many years, and I’ve found that simply moving SSH to a different port solves this problem far more elegantly. I monitor logs in order to identify incoming hacking attempts, and I haven’t seen a single one in the many years I’ve been doing this. However, using this “security by obscurity” method doesn’t mean that such an attack can’t happen, and if you don’t watch your logs regularly and respond quickly to them as I do, then you would be well advised to install fail2ban or similar as a precaution, in addition to moving your SSH server to another port as described above.
  3. Once you’ve hardened your server, you’re advised to run some vulnerability scans and penetration tests against it in order to check that it’s actually as invincible as you’re now hoping it is. This is a topic which requires a post all of its own so I won’t be covering it in any detail here, but a good starting point if you’re not already familiar with it is the excellent Nmap security scanner.