If you haven’t read it before, check out the post WordPress Configuration and Security Tips [Link]. It has security measures related to WordPress, but many of them are applicable to other websites as well.


Preventing Hot-Links

Hot-linking is when a website copies the direct URL of an image from another site and embeds it on their own. This reduces traffic on their server while increasing it on the original site’s server.

Start by setting up Apache to use .htaccess files.

sudo nano /etc/apache2/sites-available/000-default.conf

Make sure you have this configuration in your website block (also verify that the full path matches your site root):

<Directory /var/www/html>
AllowOverride All
</Directory>

Create or edit the .htaccess file at the root of your site:

sudo nano /var/www/html/.htaccess

Include the content below, replacing example.com with your own domain:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example.com [NC]
RewriteRule \.(gif|png|jpeg|jpg|svg)$ - [F]

Enable the module and restart Apache.

a2enmod rewrite
sudo systemctl restart apache2

Apache ModSecurity

ModSecurity is an intrusion detection and prevention system.

IMPORTANT

This feature must be thoroughly tested to avoid breaking web application functionality. I do not recommend it for WordPress and many other applications.

sudo apt install libapache2-mod-security2 -y
sudo a2enmod headers
sudo systemctl restart apache2

By default, it comes with a basic set of rules, but for better coverage replace them with the OWASP CoreRuleSet [Link].

sudo mv /usr/share/modsecurity-crs/ /usr/share/modsecurity-crs.bkp/
sudo git clone https://github.com/coreruleset/coreruleset /usr/share/modsecurity-crs/
sudo cp /usr/share/modsecurity-crs/crs-setup.conf.example /usr/share/modsecurity-crs/crs-setup.conf
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
sudo nano /etc/modsecurity/modsecurity.conf

Edit:

SecRuleEngine On

For each enabled site, add the following lines:

<VirtualHost *:443>
...
     SecRuleEngine On
     <IfModule security2_module>
          Include /usr/share/modsecurity-crs/crs-setup.conf
          Include /usr/share/modsecurity-crs/rules/*.conf
     </IfModule>
...
</VirtualHost>

Restart Apache:

sudo systemctl reload apache2

To test the security module, try accessing any URL with an injection payload:

https://example.com/?exec=/bin/bash

Restrict Access using Basic Authentication

These techniques have similar equivalents on NGINX.

sudo apt-get install apache2-utils
sudo htpasswd -c /etc/apache2/.htpasswd user1
sudo htpasswd /etc/apache2/.htpasswd user2
...
sudo htpasswd -D /etc/apache2/.htpasswd user1

Create each user and set its password as shown above.

  • Notes:
    • -c
      • Creates the file to store credentials. Use this flag only when adding the first user.
    • -D
      • Removes a user’s credentials from the file.
    • See the official Apache htpasswd documentation [Link].

Edit the desired site configuration and add the bold lines accordingly:

<Directory /var/www/html/>
...

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

</Directory>

Restrict Access by Source IP or Network

<Directory /var/www/html/>
...
Require not ip 192.168.0.5
Require ip 192.168.0.0/16
Require ip 10.0.0.0

</Directory>

Customize the lines above according to your needs.

Restart Apache:

sudo systemctl restart apache2

Swap and Memory Usage

For small instances with limited RAM (such as 1GB), a swap file is necessary to prevent the server from crashing under a simple fuzz or crawl attack.

Create and allocate extra swap space:

sudo fallocate -l 2G /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1024 count=2097152
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

To make it persistent across reboots:

sudo nano /etc/fstab

Append:

/swapfile swap swap defaults 0 0

Then test:

sudo mount -a

Throttling Traffic

Check how much memory each Apache process uses to estimate how many instances your server should be limited to:

ps -ylC apache2 --sort:rss | awk '{sum+=$8; ++n} END {print "\n Average = "sum/1024" MB / "n-1" Threads = "sum/(n-1)/1024" MB \n"}'

Let the server run for a couple of weeks before checking its usage with the command above, as it adjusts over time based on demand.

Edit the MPM module:

sudo nano /etc/apache2/mods-available/mpm_prefork.conf

Recommended settings for 1 CPU with 1GB RAM running LAMP:

StartServers               1
MinSpareServers            2
MaxSpareServers            5
MaxRequestWorkers          10
MaxConnectionsPerChild     2000

Recommended settings for 1 CPU with 1GB RAM running only Apache with PHP and an external database:

StartServers               5
MinSpareServers            5
MaxSpareServers            10
MaxRequestWorkers          70
MaxConnectionsPerChild     0

Restart Apache:

sudo systemctl restart apache2