Disable/Prevent hotlinking of your Drupal images in Varnish or Apache

I'm going to assume you know what image hotlinking is and get to the details of prevention. The easiest to way to setup hotlinking prevention is to disable it in your Drupal site's .htaccess file. There are a few problems with this method:

  • This type of site-wide configuration should be handled by the system administrator. A web developer shouldn't be able to (accidentally) disable it.
  • It's yet another thing to remember to check during a Drupal core upgrade.
  • If you are running Varnish, this method won't work: Varnish will cache the redirect for anonymous users.

Goal: detect image/file hotlinking and display an explanation image to the user instead.

Apache Server Virtualhost Drupal Hotlink Prevention settings
If you have Varnish, you cannot use this method.
Edit your site's Apache Server Virtualhost file, generally stored in: /etc/apache2/sites-available/ on Ubuntu/Debian. Add the following within the <VirtualHost> and outside any <Directory> directive:

# Enable the rewrite engine, mod_rewrite must be enabled.
RewriteEngine On
# Allow empty referers
RewriteCond %{HTTP_REFERER} !^$
# Allow example.com and all sub-domains. Duplicate this line to allow more domains.
RewriteCond %{HTTP_REFERER} !^http(s)?://(.*\.)?example.com [NC]
# Only prevent hotlinking of Drupal files; the explanation image must be located outside of the Drupal files directory.
RewriteCond %{REQUEST_URI} ^/sites/default/files/
# Rewrite all jpeg, jpg, gif, and png images to the explanation image.
RewriteRule \.(jpeg|jpg|gif|png)$ http://example.com/sites/all/themes/my_theme/images/image-hotlinking-disabled.jpg [NC,R,L]

Varnish Drupal Hotlink Prevention settings
Edit your site's Varnish configuration file, generally stored in: /etc/varnish/default.vcl on Ubuntu/Debian, and add the following to vcl_rev():

sub vcl_recv {
  # If the request host is example.com AND
  # the URL starts with /sites/default/files AND
  # the HTTP referer is set AND the referer is not http://example.com
  if (req.http.host ~ "example.com" &&
    req.url ~ "^/sites/default/files/" &&
    (req.http.referer && req.http.referer !~ "^http://example.com")) {
      # Rewrite the request URL to the explanation image.
      set req.url = "http://example.com/sites/all/themes/my_theme/images/image-hotlinking-disabled.jpg";

Further research required to make sure cache max age is set to zero for any hotlinked image. TBD.

Make sure to test your settings thoroughly before enabling either option your production websites/servers. Here is a good method to: Reload your Varnish configuration without a restart.