{"id":674,"date":"2020-12-29T21:22:27","date_gmt":"2020-12-29T21:22:27","guid":{"rendered":"https:\/\/dft.wiki\/?p=674"},"modified":"2026-04-21T13:35:27","modified_gmt":"2026-04-21T17:35:27","slug":"prevent-hot-links-on-apache","status":"publish","type":"post","link":"https:\/\/dft.wiki\/?p=674","title":{"rendered":"Increasing Security and Availability of Apache on Ubuntu"},"content":{"rendered":"<p>If you haven&#8217;t read it before check out the post WordPress Configuration and Security Tips [<a href=\"https:\/\/dft.wiki\/?p=405\">Link<\/a>]. It has security measures related to WordPress, but many of them are applicable to many other websites.<\/p>\n<hr \/>\n<p><strong>Preventing Hot-Links<\/strong><\/p>\n<p>Hot-Links are when one website developer copies the original link of an image, for example, from one site to their site. It reduces the data traffic on his server but increases the traffic on someone else&#8217;s server.<\/p>\n<p>Start setting up your Apache to use <strong>.htaccess<\/strong> files.<\/p>\n<pre>sudo nano \/etc\/apache2\/sites-available\/000-default.conf<\/pre>\n<p>Make sure you have this type of configuration in the block of your website (also check if the full path matches your site root):<\/p>\n<pre>&lt;Directory \/var\/www\/html&gt;\r\nAllowOverride All\r\n&lt;\/Directory&gt;<\/pre>\n<p>Create or edit the .htaccess file at the root of your site:<\/p>\n<pre>sudo nano \/var\/www\/html\/.htaccess<\/pre>\n<p>Include this content, but change example.com to your own domain:<\/p>\n<pre>RewriteEngine on\r\nRewriteCond %{HTTP_REFERER} !^$\r\nRewriteCond %{HTTP_REFERER} !^http(s)?:\/\/(www\\.)?<strong>example.com<\/strong> [NC]\r\nRewriteRule \\.(gif|png|jpeg|jpg|svg)$ - [F]<\/pre>\n<p>Enable the module and restart your Apache.<\/p>\n<pre>a2enmod rewrite\r\nsudo systemctl restart apache2<\/pre>\n<hr \/>\n<p><strong>Apache ModSecurity<\/strong><\/p>\n<p>It is an intrusion detection and prevention system.<\/p>\n<p>IMPORTANT<\/p>\n<p style=\"padding-left: 40px;\">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.<\/p>\n<pre>sudo apt install libapache2-mod-security2 -y\r\nsudo a2enmod headers\r\nsudo systemctl restart apache2<\/pre>\n<p>By default, it comes with a set of rules but for better performance replace it with the OWASP CoreRuleSet [<a href=\"https:\/\/github.com\/coreruleset\/coreruleset\">Link<\/a>].<\/p>\n<pre>sudo mv \/usr\/share\/modsecurity-crs\/ \/usr\/share\/modsecurity-crs.bkp\/\r\nsudo git clone https:\/\/github.com\/coreruleset\/coreruleset \/usr\/share\/modsecurity-crs\/\r\nsudo cp \/usr\/share\/modsecurity-crs\/crs-setup.conf.example \/usr\/share\/modsecurity-crs\/crs-setup.conf\r\nsudo cp \/etc\/modsecurity\/modsecurity.conf-recommended \/etc\/modsecurity\/modsecurity.conf\r\nsudo nano \/etc\/modsecurity\/modsecurity.conf<\/pre>\n<p>Edit:<\/p>\n<pre>SecRuleEngine <strong>On<\/strong><\/pre>\n<p>For each of the enabled sites add the following lines:<\/p>\n<pre>&lt;VirtualHost *:443&gt;\r\n...\r\n     <strong>SecRuleEngine On<\/strong>\r\n<strong>     &lt;IfModule security2_module&gt;<\/strong>\r\n<strong>          Include \/usr\/share\/modsecurity-crs\/crs-setup.conf<\/strong>\r\n<strong>          Include \/usr\/share\/modsecurity-crs\/rules\/*.conf<\/strong>\r\n<strong>     &lt;\/IfModule&gt;<\/strong>\r\n...\r\n&lt;\/VirtualHost&gt;<\/pre>\n<p>Restart Apache<\/p>\n<pre>sudo systemctl reload apache2<\/pre>\n<p>To test the security module try to access any link with an injection code:<\/p>\n<pre>https:\/\/example.com\/?exec=\/bin\/bash<\/pre>\n<hr id=\"BasicAuthentication\" \/>\n<p><strong>Restrict Access using Basic Authentication<\/strong><\/p>\n<p>These techniques have similar functionality on NGINX.<\/p>\n<pre>sudo apt-get install apache2-utils\r\nsudo htpasswd <span style=\"color: #0000ff;\"><strong>-c<\/strong><\/span> \/etc\/apache2\/.htpasswd <strong>user1<\/strong>\r\nsudo htpasswd \/etc\/apache2\/.htpasswd <strong>user2\r\n...\r\n<\/strong>sudo htpasswd <span style=\"color: #ff0000;\"><strong>-D<\/strong><\/span> \/etc\/apache2\/.htpasswd <strong>user1\r\n<\/strong><\/pre>\n<p>Create each user and set its password as shown above.<\/p>\n<ul>\n<li>Note:\n<ul>\n<li><strong><span style=\"color: #0000ff;\">-c<\/span><\/strong>\n<ul>\n<li>Creates the file to store the credentials and should only be used while adding the first user.<\/li>\n<\/ul>\n<\/li>\n<li><strong><span style=\"color: #ff0000;\">-D<\/span><\/strong>\n<ul>\n<li>Removes user&#8217;s credentials from the file.<\/li>\n<\/ul>\n<\/li>\n<li>See the official documentation about Apache htpasswd at [<a href=\"https:\/\/httpd.apache.org\/docs\/2.4\/programs\/htpasswd.html\">Link<\/a>].<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Edit the desired site configuration and add bold lines accordingly:<\/p>\n<pre class=\" prettyprinted\"><span class=\"tag\">&lt;Directory<\/span> <span class=\"pun\">\/<\/span><span class=\"atn\">var<\/span><span class=\"pun\">\/<\/span><span class=\"atn\">www<\/span><span class=\"pun\">\/<\/span><span class=\"atn\">html<\/span><span class=\"tag\">\/&gt;<\/span><span class=\"pln\">\r\n...\r\n\r\n<\/span><strong><span class=\"pln\">AuthType Basic<\/span><\/strong>\r\n<strong><span class=\"pln\">AuthName \"Restricted Content\"<\/span><\/strong>\r\n<strong><span class=\"pln\">AuthUserFile \/etc\/apache2\/.htpasswd<\/span><\/strong>\r\n<strong><span class=\"pln\">Require valid-user<\/span><\/strong>\r\n<span class=\"tag\">\r\n&lt;\/Directory&gt;<\/span><\/pre>\n<p><strong>Restrict Access from Source IP or Network<\/strong><\/p>\n<pre class=\" prettyprinted\"><span class=\"tag\">&lt;Directory<\/span> <span class=\"pun\">\/<\/span><span class=\"atn\">var<\/span><span class=\"pun\">\/<\/span><span class=\"atn\">www<\/span><span class=\"pun\">\/<\/span><span class=\"atn\">html<\/span><span class=\"pun\">\/<\/span><span class=\"tag\">&gt;<\/span><span class=\"pln\">\r\n...\r\n<strong>Require not ip 192.168.0.5\r\nRequire ip 192.168.0.0\/16\r\nRequire ip 10.0.0.0\r\n<\/strong><\/span><span class=\"tag\">\r\n&lt;\/Directory&gt;<\/span><\/pre>\n<p>Customize the lines above according to your needs.<\/p>\n<p>Restart Apache2<\/p>\n<pre>sudo systemctl restart apache2<\/pre>\n<hr \/>\n<p><strong>Swap and Memory Usage<\/strong><\/p>\n<p>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.<\/p>\n<p>Create and Allocate extra Swap<\/p>\n<pre>sudo fallocate -l 2G \/swapfile\r\nsudo dd if=\/dev\/zero of=\/swapfile bs=1024 count=2097152\r\nsudo chmod 600 \/swapfile\r\nsudo mkswap \/swapfile\r\nsudo swapon \/swapfile<\/pre>\n<p>To make it persistent after rebooting:<\/p>\n<pre>sudo nano \/etc\/fstab<\/pre>\n<p>Append:<\/p>\n<pre>\/swapfile swap swap defaults 0 0<\/pre>\n<p>And test:<\/p>\n<pre>sudo mount -a<\/pre>\n<hr \/>\n<p><strong>Throttling Traffic<\/strong><\/p>\n<p>Check how much memory each instance of Apache using to estimate how many instances your server has to be limited to:<\/p>\n<pre>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\"}'<\/pre>\n<p>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.<\/p>\n<p>Edit the MPM module:<\/p>\n<pre>sudo nano \/etc\/apache2\/mods-available\/mpm_prefork.conf<\/pre>\n<p>For 1 CPU with 1 GB RAM running LAMP is recommended:<\/p>\n<pre>StartServers               1\r\nMinSpareServers            2\r\nMaxSpareServers            5\r\nMaxRequestWorkers          10\r\nMaxConnectionsPerChild     2000<\/pre>\n<p>For 1 CPU with 1 GB RAM running Only Apache with PHP and accessing an external Database is recommended:<\/p>\n<pre>StartServers               5\r\nMinSpareServers            5\r\nMaxSpareServers            10\r\nMaxRequestWorkers          70\r\nMaxConnectionsPerChild     0<\/pre>\n<p>Restart Apache2<\/p>\n<pre>sudo systemctl restart apache2<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>If you haven&#8217;t read it before check out the post WordPress Configuration and Security Tips [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-674","post","type-post","status-publish","format-standard","hentry","category-web"],"_links":{"self":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/674","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=674"}],"version-history":[{"count":17,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/674\/revisions"}],"predecessor-version":[{"id":5492,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/674\/revisions\/5492"}],"wp:attachment":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=674"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=674"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=674"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}