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 many other websites.


Preventing Hot-Links

Hot-Links are when one website developer copies the original link of an image, for example from one site to his site. It reduces the data traffic in his server but increases the traffic on someone else’s server.

Start setting up your Apache to use .htaccess files.

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

Make sure you have this type of configuration in the block of your website (also check if the full path matched with 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 this content but change the example.com by 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 your Apache.

a2enmod rewrite
sudo systemctl restart apache2

Apache ModSecurity

It is an intrusion detection and prevention system.

IMPORTANT

This feature must be very well tested to prevent interruption of the web application functionalities. 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 set of rules but for better performance replace it 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 of the enabled sites 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 to access any link with an injection code:

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

Restrict Access using Basic Authentication

These techniques have similar functionality 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.

  • Note:
    • -c
      • Creates the file to store the credentials and should only be used while adding the first user.
    • -D
      • Removes user’s credentials from the file.
    • See the official documentation about Apache htpasswd at [Link].

Edit the desired site configuration and add bold lines accordingly:

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

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

</Directory>

Restrict Access from 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 Apache2

sudo systemctl restart apache2

Swap and Memory Usage

For tiny instances that have limited RAM (such as 1GB), it is necessary to have a Swap file to prevent the server to crash over a simple Fuzz or Crawl.

Create and Allocate extra Swap

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

To make it persistent after rebooting:

sudo nano /etc/fstab

Append:

/swapfile swap swap defaults 0 0

And test:

sudo mount -a

Throttling Traffic

Check how much memory each instance of Apache using to estimate how many instances your server has to 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"}'

It is important to leave the server running for a couple of weeks before check its usage (command above) because it adjusts with the demand.

Edit the MPM module:

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

For 1 CPU with 1 GB RAM running LAMP is recommended:

StartServers               1
MinSpareServers            2
MaxSpareServers            5
MaxRequestWorkers          10
MaxConnectionsPerChild     2000

For 1 CPU with 1 GB RAM running Only Apache with PHP and accessing an external Database is recommended:

StartServers               5
MinSpareServers            5
MaxSpareServers            10
MaxRequestWorkers          70
MaxConnectionsPerChild     0

Restart Apache2

sudo systemctl restart apache2