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].
- -c
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