Apache is the most popular open source web server available for modern Linux servers. It offers flexible configuration allowing for a wide variety of uses, from serving basic HTML sites, to complex PHP/Passenger applications, to proxying requests as a reverse proxy gateway. Given its popularity and easy of use, it’s essential to install and maintain a secure environment for Apache installations.
This article assumes you've installed and configured Apache on a Debian or Ubuntu instance:
Keep Apache updated
Apache has a good security track record, and security bugs are seldom found within the web server itself. Still, it’s important to keep Apache updated in order to take advantage of the latest security, stability and features available. Generally, this is simply a matter of keeping the Apache package provided by the distribution's OS updated (e.g. via apt, yum, etc). It’s also recommended that Apache server operators following the Apache Server Announcements mailing list to stay up to date with the latest news from the Apache development team. You can subscribe to the list here:
Apache is built to be stable and secure, but it will only be as secure as the user who configures it. Once Apache is built and installed, it’s important to configure the server to be as minimal as possible.
Run as an unprivileged user
In security, the principle of least privilege states that an entity should be given no more permission than necessary to accomplish its goals within a given system. In the context of your web server, this means locking down Apache to run only with the permissions necessary to run. A first step in this process is to configure Apache to run as an unprivileged system user (e.g., not root). This is done by setting the APACHE_RUN_USER and APACHE_RUN_GROUP variables in the /etc/apache2/envvars file:
Edit the file and change the following lines:
[user@server]$ sudo vim /etc/apache2/envvars # Since there is no sane way to get the parsed apache2 config in scripts, some # settings are defined via environment variables and then used in apache2ctl, # /etc/init.d/apache2, /etc/logrotate.d/apache2, etc. export APACHE_RUN_USER=apache export APACHE_RUN_GROUP=apache
Apache servers distributed as a common OS package may also use a user and group name such as www-data or nobody. Regardless of the choice of user’s name, make sure that the user/group selection has as few rights as necessary to run properly.
The HTTP spec recommends (but not requires) that web servers identify themselves via the Server header. Historically, web servers have included their version information as part of this header. Disclosing the version of Apache running can be undesirable, particularly in environments sensitive to information disclosure. Configure Apache not to display its version in Server header by editing the following file:
[user@server]$ sudo vim /etc/apache2/conf-available/security.conf
In that file you'll see several 'ServerTokens'. Make sure they are all commented out and only 'ProductOnly' appears.
# ServerTokens #ServerTokens Minimal #ServerTokens OS #ServerTokens Full ServerTokens ProductOnly;
Restart Apache to update the changes.
[user@server]$ sudo service apache2 reload
Disable .htaccess files
.htaccess files are a powerful feature that allow Apache to have its configuration extended outside its main config file. While this may be convenient, it does present a security risk, as Apache will read any .htaccess file in its path — even ones placed by an attacker that could compromise the server. It may be desirable to lock down the Apache configuration by disabling .htaccess files entirely. This can be done by editing the AllowOverride directive in the /etc/apache2/apache2.conf file:
[user@server]$ sudo vim /etc/apache2/apache2.conf AllowOverride None
Additionally, fine-grained control of which Apache directives can be used within .htaccess files can also be controlled by AllowOverride:
AllowOverride AuthConfig Indexes
In the example above, all directives that are neither in the group AuthConfig nor Indexes cause an internal server error. View the following site for further details:
Restrict access by IP
Sensitive areas of websites, such as admin control panels, should have strict access controls placed on them. Apache makes it easy to whitelist IP access to certain locations of your website and deny traffic to all other IP addresses. You can add the following to your /etc/apache2/apache2.conf file.
<Directory /PATH/TO/WEBDIR/wp-admin> # allow access from one IP and an additional IP range, # and block everything else Require ip 220.127.116.11 Require ip 192.168.0.0/24 </Directory>
In this example, the use of the Require directive instructs Apache to allow access to the specified path if the requests come from any of the IP addresses listed, and to deny all other traffic.
Restrict Access by Password
Access to certain locations can also be set via password-based credentials, using the htpasswd utility. View the following article for further details:
Preventing DoS attacks
The default model in which Apache processes requests (called prefork mode), is subject to an attack known as a Slowloris attack. A Slowloris attack is a form of DoS (Denial of Service) attack in which the Apache server is forced to wait on requests from malicious clients taking a long time to send traffic, thus forcing legitimate requests to time out or be ignored entirely. Thankfully, modern Apache servers are capable of mitigating this threat with a few additional configuration directives.
mod_reqtimeout is an Apache module designed to shut down connections from clients taking too long to send their request, such as is seen in a Slowloris attack. This module provides a directive that allows Apache to close the connection if it senses that the client is not sending data quickly enough. For example, add this to your /etc/apache2/apache2.conf file:
RequestReadTimeout header=10-20,MinRate=500 body=20,MinRate=500
In this example, Apache will close the connection if the client takes more than 10 seconds to send its HTTP headers, or if the client takes more than 20 seconds to send headers at a rate of 500 bytes per second.
Apache will also close the connection if the client takes more than 20 seconds to send its request body, but will allow the request to continue as long as the client sends more than 500 bytes per second.
This configuration allows clients with poor TCP connection quality (such as remote clients with high latency, or those on low-grade cellular or satellite networks) to send requests, while still protecting against known fingerprints of the Slowloris attack. RequestReadTimeout configurations can be complex, so it's recommended you review more information about this directive at the module documentation page.
Make sure all sites on your server have an SSL certificate installed. You can install a free 'Let's Encrypt' certificate using the following instructions:
Force all connections over TLS
If you've installed a 'Let's Encrypt' certificate as shown above, you already had the option to force all traffic over SSL. If you're not using a 'Let's Encrypt' certificate, you can also do this by adding the following to your site's configuration file located at /etc/apache2/sites-available/example.com.conf.
First, make sure the Headers module is active.
[user@server]$ sudo a2enmod headers [user@server]$ sudo service apache2 restart
You can then add the following to your site's .conf file.
<IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" </IfModule>
For all plaintext connections, configure Apache to send a 301 redirect for requests to the TLS version of the site:
<VirtualHost 192.168.1.1:80> [...] ServerName example.com Redirect permanent / https://example.com/ </VirtualHost>
Additional security measures
Beyond the basics of installing a secure Apache binary, locking down access to sensitive areas of your site and properly serving TLS connections, there are some additional steps that the extra security-conscious user can take:
Install a WAF
A WAF (web application firewall) is a piece of software designed to inspect HTTP/HTTPS traffic, deny malicious requests, and generally act as an additional layer of security in an HTTP web stack. A properly configured WAF can protect your site from SQLi, XSS, CSRF, and DDoS attacks, as well as provide brute force attack mitigation and zero-day threat patching. The most popular and stable WAF for Apache is ModSecurity. View the project’s GitHub page for more information on installation and configuration.
Automated Log Analysis + Monitoring
Programs like Fail2Ban can be used to monitor Apache access and error logs, searching for attack patterns and taking actions against the attacking client (such as dropping IP addresses, reporting malicious behavior to the IP’s owner, etc). Fail2Ban is extensible, allowing for the creation of unique search patterns and response behaviors. For more information and details on installation and configuration, see the project's GitHub page:
Limit input traffic via IPTables
Beyond securing Apache itself, it’s important to secure the host environment used to host the web server. Locking down access to things like SSH can greatly increase the security of the host by preventing intrusion attempts. A common approach is to whitelist known IPs that will access the host via SSH and deny all other port 22 traffic, or to use a jump box that strictly filters shell access. You can also do this by configuring a custom security group for your instance. View the following article for more information: