Introduction

As the software in your web application that directly handles all requests coming in from the Internet, Apache is extremely vulnerable to attack. While adding a cloud-based WAF service like SecureCDN in front of your application prevents threats from getting through in the first place, there are some measures you can take to secure Apache iteself. In this article we'll show you which measures those are, and how to implement them.

While creating this article and testing different security measures, the latest versions of the Apache web server (2.4) and Ubuntu server (16.04) were used. That being the case, many earlier versions of Apache and Ubuntu support the configurations recommended below.

Prerequsities

Before getting started you should have a basic understanding of the following:

  1. Common file editors like nano
  2. Basic directory moving (cd)

Also be aware that this article was created with a fresh installation of Apache, but the configurations can also be applied to production servers (with proper maintenance windows and backups.) If you're hardening a server in production, simply skip the steps you've already completed (Apache installation, creating the .htaccess file, etc.)

Steps for Hardining Apache 2.4

Install Apache

Install the latest version of the Apache2 server:

sudo apt-get install apache2

Disable Server Signature

Edit /etc/apache2/apache2.conf:

sudo nano /etc/apache2/apache2.conf

Add the following lines. You can add them to the end of the file:

ServerSignature OFF
ServerTokens Prod

Edit /etc/apache2/conf-available/security.conf:

sudo nano /etc/apache2/conf-available/security.conf

Edit the following line:

ServerSignature Off

Prevent Denial of Service

Make sure you have the following lines in the file /etc/apache2/apache2.conf:

Timeout 300
KeepAlive On
MaxKeepAliveTimeout5
MaxRequestWorkers 250
LimitRequestFields 100
LimitRequestFieldSize 8190

If you don’t, add and save them. Just be careful not to duplicate the lines.

User and Groups for Apache

Add the group Apache:

sudo groupadd apache

Add the user apache with nologin bash belonging to group Apache:

sudo useradd -d /var/www/ -g apache -s /bin/nologin apache

Edit the file /etc/apache2/apache2.conf:

sudo nano /etc/apache2/apache2.conf

Comment out the User and Group lines:

User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

#User ${APACHE_RUN_USER}
#Group ${APACHE_RUN_GROUP}

Add the following lines and save the file:

User apache
Group apache

Locate modules and, depending on your case, eliminate the module you don’t need. First, you can list them:

sudo apachectl -M
Loaded Modules:
 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)
 log_config_module (static)
.
.
 autoindex_module (shared)
 deflate_module (shared)

The next example is to unload the Directory Listing Module (the autoindex module).

Prevent Directory Listing

Run a2dismod to disable the module autoindex (that does the Directory Listing):

sudo a2dismod -f autoindex

Then restart the service (and test it with a browser):

sudo service apache2 reload

Protect .htaccess File

Edit the file /etc/apache2/apache2.conf:

sudo nano /etc/apache2/apache2.conf

Add the following lines and save the file:

<Directory "/">
AllowOverride None
</Directory>

Add Apache Module for Evasive Mode to Prevent DoS

First install the module:

sudo apt-get install libapache2-mod-evasive

Check that it was included into Apache:

sudo apachectl –M

Loaded Modules:
.
.
.
 authz_host_module (shared)
 authz_user_module (shared)
 deflate_module (shared)
 dir_module (shared)
 env_module (shared)
 evasive20_module (shared)
 filter_module (shared)

Edit the file /etc/apache2/mods-enabled-evasive.conf:

sudo nano /etc/apache2/mods-enabled-evasive.conf

Uncomment the lines between <Ifmodule mod_evasive20.c> and </IfModule> and save the file:

<IfModule mod_evasive20.c>
    #DOSHashTableSize    3097
    #DOSPageCount        2
    #DOSSiteCount        50
    #DOSPageInterval     1
    #DOSSiteInterval     1
    #DOSBlockingPeriod   10

    #DOSEmailNotify      you@yourdomain.com
    #DOSSystemCommand    "su - someuser -c '/sbin/... %s ...'"
    #DOSLogDir           "/var/log/mod_evasive"
</IfModule>


<IfModule mod_evasive20.c>
    DOSHashTableSize    3097
    DOSPageCount        2
    DOSSiteCount        50
    DOSPageInterval     1
    DOSSiteInterval     1
    DOSBlockingPeriod   10

    DOSEmailNotify      you@yourdomain.com
    DOSSystemCommand    "su - someuser -c '/sbin/... %s ...'"
    DOSLogDir           "/var/log/mod_evasive"
</IfModule>

Then restart the service:

sudo service apache2 reload

Enable Web Application Firewall (WAF) – Detection Only (Modsecurity)

It’s recommended to start this WAF in detection-only mode (like an IDS) to prevent too many false positives. You should start with this option to test traffic patterns, then you can start to block traffic based on the potential threats you discover.

First install the module:

sudo apt-get install libapache2-mod-security2

Check that it was included in Apache:

sudo apachectl –M

Loaded Modules:
.
.
.
mime_module (shared)
 mpm_event_module (shared)
 negotiation_module (shared)
 security2_module (shared)
 setenvif_module (shared)

Rename the file /etc/modsecurity/modsecurity.conf-recommended to modsecurity.conf (modsecurity searches for configuration files that end with. conf):

sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

Check the audit file created in /var/log/apache2 (navigate “cd” to that directory):

/var/log/apache2$ ls -l modsec_audit.log 
-rw-r----- 1 root root 0 Sep 11 16:09 modsec_audit.log

The rules for the WAF should be used. To configure and enable the rules, edit /etc/apache2/modsecurity/security2.conf:

sudo nano /etc/apache2/mods-enabled/security2.conf

Add the following two lines and save the file:

<IfModule security2_module>

Include "/usr/share/modsecurity-crs/*.conf"
Include "/usr/share/modsecurity-crs/activated_rules/*.conf"

For adding the rules, you should create symbolic links to the rules files. These links should be created on /usr/share/modsecurity-crs/activated_rules/.

Add the rules below for IDS (Intrusion Detection System) validation of:

  • SQL Injections
  • HTTP Protocol violations
  • HTTP Anomalies
  • Request Limits

Go to directory /usr/share/modsecurity-crs/activated_rules:

cd /usr/share/modsecurity-crs/activated_rules

Create the rules (with the symbolic links):

/usr/share/modsecurity-crs/activated_rules$ sudo ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf
/usr/share/modsecurity-crs/activated_rules$ sudo ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_20_protocol_violations.conf
/usr/share/modsecurity-crs/activated_rules$ sudo ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_21_protocol_anomalies.conf
/usr/share/modsecurity-crs/activated_rules$ sudo ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_23_request_limits.conf

Restart the service:

sudo service apache2 reload

Password Authentication (for Web Pages that Require this Type of Authentication)

Create the Apache password for the user “Joe” with the htpasswd utility:

sudo htpasswd -c /etc/apache2/.htpasswd joe
New password: 
Re-type new password: 
Adding password for user joe

Replace Joe with the user you want to use.

Take a look at the file to see that the user and password were added:

sudo cat /etc/apache2/.htpasswd 
joe:$apr1$DRpg9jcY$BxTlqPmnLPB/sVEocBGUA/

Edit the file /etc/apache2/apache2.conf:

sudo nano /etc/apache2/apache2.conf

Add the following line after <Directory /var/www>. In case the line exists, modify variable AllowOverride to “None” value:

<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>

Create .htaccess in the root directory for the website and add the following lines (e.g. /var/www/html/.htaccess).

Create /var/www/html/.htaccess in the the root directory for the website:

sudo nano /var/www/html/.htaccess

Add the following lines, then save the file:

AuthType Basic
AuthName "Restricted Content"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

Restart the service:

sudo service apache2 reload

When you access the page in /var/www/html from a web browser, it’s going to authenticate you. This can be used to password-protect some pages inside the site.

Install Fail2ban for Banning Persistent Authentication Failures

Install fail2ban:

sudo apt-cache search fail2ban

Create the new file /etc/fail2ban/jail.local:

sudo nano /etc/fail2ban/jail.local

Add the following lines and save the file:

[apache]
enabled  = true
port     = http,https
filter   = apache-auth
logpath  = /var/log/apache2/*error.log
maxretry = 3
findtime = 600
#ignoreip = x.x.x.x

[apache-noscript]
enabled  = true
port     = http,https
filter   = apache-noscript
logpath  = /var/log/apache2/*error.log
maxretry = 3
findtime = 600
#ignoreip = x.x.x.x

[apache-overflows]
enabled  = true
port     = http,https
filter   = apache-overflows
logpath  = /var/log/apache2/*error.log
maxretry = 2
findtime = 600
#ignoreip = x.x.x.x

[apache-badbots]
enabled  = true
port     = http,https
filter   = apache-badbots
logpath  = /var/log/apache2/*error.log
maxretry = 2
findtime = 600
#ignoreip = x.x.x.x

Restart the service fail2ban:

sudo nano /etc/fail2ban/jail.local

Enable HTTPS and Install SSL Certificate

Enable the Apache SSL module:

sudo a2enmod ssl

Check that it’s enabled:

a2query -m ssl
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = "en_US:en",
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("en_US.UTF-8").
ssl (enabled by site administrator)

Enable the SSL template for the default website:

sudo a2ensite default-ssl.conf

Then restart the service:

sudo service apache2 reload

Create the SSL directory:

sudo mkdir /etc/apache2/ssl

Now we’ll create a self-signed SSL certificate. However, certificates should be signed by a TTP (Trusted Third Party).

Create the X.509 certificate and answer all the questions that will identify the server. In this case, the example site is www.mysite.com:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt

Generating a 2048 bit RSA private key ..............................+++ ...................................................................+++ writing new private key to '/etc/apache2/ssl/apache.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Texas Locality Name (eg, city) []:Dallas Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyUbuntuBlogStackPath Organizational Unit Name (eg, section) []:Security Dpt Common Name (e.g. server FQDN or YOUR name) []:www.mysite.com Email Address []:admin@mysite.com

Now we need to protect the certificate files and key. Go to the directory /etc/apache2/ssl, change permissions, and check it:

/etc/apache2/ssl$ sudo chmod 600 *
/etc/apache2/ssl$ ls -la
total 16
drwxr-xr-x 2 root root 4096 Sep 11 19:50 .
drwxr-xr-x 9 root root 4096 Sep 11 19:45 ..
-rw------- 1 root root 1464 Sep 11 19:50 apache.crt
-rw------- 1 root root 1704 Sep 11 19:50 apache.key

Edit the file /etc/apache2/sites-enabled/default-ssl.conf:

sudo nano /etc/apache2/sites-enabled/default-ssl.conf

Add the following lines:

<VirtualHost _default_:443>

                ServerAdmin webmaster@localhost
                ServerName www.mysite.com:443

Now locate the section:

SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile   /etc/ssl/private/ssl-cert-snakeoil.key

And replace it with:

SSLCertificateFile      /etc/apache2/ssl/apache.crt         
SSLCertificateKeyFile   /etc/apache2/ssl/apache.key

Then restart the service:

sudo service apache2 reload

Visit your site with a browser and look at the certificate. Now your users can trust that they are using the intended server and that communication is encrypted for that site.

Conclusion

You now have a solid web server to receive requests on and deliver content from. In addtion to hardening Apache, we also recommend hardening Ubuntu. You can also position a cloud-based WAF and DDoS mitigation service in front of your application to further protect it.

If you have any other suggestions for hardening Apache on Ubuntu, let us know in the comment section below.

Start 15-day Trial

Every Secure Content Delivery Plan includes WAF and DDoS mitigation.

Choose plan