{"id":674,"date":"2020-12-29T21:22:27","date_gmt":"2020-12-29T21:22:27","guid":{"rendered":"https:\/\/dft.wiki\/?p=674"},"modified":"2026-06-09T13:22:46","modified_gmt":"2026-06-09T17:22:46","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 other websites as well.<\/p>\n<hr \/>\n<p><strong>Preventing Hot-Links<\/strong><\/p>\n<p>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&#8217;s server.<\/p>\n<p>Start by setting up 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 configuration in your website block (also verify that 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 the content below, replacing example.com with 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 Apache.<\/p>\n<pre>a2enmod rewrite\r\nsudo systemctl restart apache2<\/pre>\n<hr \/>\n<p><strong>Apache ModSecurity<\/strong><\/p>\n<p>ModSecurity is an intrusion detection and prevention system.<\/p>\n<p>IMPORTANT<\/p>\n<p style=\"padding-left: 40px;\">This feature must be thoroughly tested to avoid breaking web application functionality. 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 basic set of rules, but for better coverage replace them 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 enabled site, 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 accessing any URL with an injection payload:<\/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 equivalents 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>Notes:\n<ul>\n<li><strong><span style=\"color: #0000ff;\">-c<\/span><\/strong>\n<ul>\n<li>Creates the file to store credentials. Use this flag only when adding the first user.<\/li>\n<\/ul>\n<\/li>\n<li><strong><span style=\"color: #ff0000;\">-D<\/span><\/strong>\n<ul>\n<li>Removes a user&#8217;s credentials from the file.<\/li>\n<\/ul>\n<\/li>\n<li>See the official Apache htpasswd documentation [<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 the 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 by 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 Apache:<\/p>\n<pre>sudo systemctl restart apache2<\/pre>\n<hr \/>\n<p><strong>Swap and Memory Usage<\/strong><\/p>\n<p>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.<\/p>\n<p>Create and allocate extra swap space:<\/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 across reboots:<\/p>\n<pre>sudo nano \/etc\/fstab<\/pre>\n<p>Append:<\/p>\n<pre>\/swapfile swap swap defaults 0 0<\/pre>\n<p>Then test:<\/p>\n<pre>sudo mount -a<\/pre>\n<hr \/>\n<p><strong>Throttling Traffic<\/strong><\/p>\n<p>Check how much memory each Apache process uses to estimate how many instances your server should 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>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.<\/p>\n<p>Edit the MPM module:<\/p>\n<pre>sudo nano \/etc\/apache2\/mods-available\/mpm_prefork.conf<\/pre>\n<p>Recommended settings for 1 CPU with 1GB RAM running LAMP:<\/p>\n<pre>StartServers               1\r\nMinSpareServers            2\r\nMaxSpareServers            5\r\nMaxRequestWorkers          10\r\nMaxConnectionsPerChild     2000<\/pre>\n<p>Recommended settings for 1 CPU with 1GB RAM running only Apache with PHP and an external database:<\/p>\n<pre>StartServers               5\r\nMinSpareServers            5\r\nMaxSpareServers            10\r\nMaxRequestWorkers          70\r\nMaxConnectionsPerChild     0<\/pre>\n<p>Restart Apache:<\/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":18,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/674\/revisions"}],"predecessor-version":[{"id":5805,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/674\/revisions\/5805"}],"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}]}}