Fork me on GitHub

Protecting Files Against Hotlinking with PHP, Lighttpd, Apache & X-Sendfile

Protecting Files Against Hotlinking with PHP, Lighttpd, Apache & X-Sendfile

I recently had to lock down some important files that first required some level of authentication. The problem was the only way to guard against hotlinking or direct access to these files was to pipe the data through php after an Auth check. Using fread, readfile or file_get_contents produced extreme CPU usage, not really to my surprise. Usually I wouldn’t care about high CPU usage on smaller projects, however this was causing the webserver to become unresponsive as it had to fully parse the files.

I went searching and eventually came across a module for both Apache and Lighttpd called X-Sendfile. The module works by sending headers out to the webserver to simply output a static file, without touching PHP’s file handling functions. First we need to install the module before we can start sending headers out to the webserver.

Apache:

  1. Login as root or your administrator account
  2. Download the following code to your server mod_xsendfile.c
  3. Installing is simple with: sudo apxs -cia mod_xsendfile.c
  4. You will now notice the messages on the screen stating it has been added to your Apache config file and copied to the apache modules directory
  5. Restart Apache. Done :)

Lighttpd

Setting up X-Sendfile on Lighttpd is much simpler as the module is shipped with Lighttpd 1.4+. All we will need to do is add in the “allow-x-send-file” => “enable” setting to our fastcgi.server array:

fastcgi.server = ( ".php" =>
  ( "localhost" =>
    ("socket" => "/opt/local/var/run/lighttpd/php-fastcgi.socket",
     "allow-x-send-file" => "enable",
     .......etc
    )
  )
)

PHP & Lighttpd

Next up we will handle some basic user authentication with PHP to show how you can protect your files with PHP:

<?php

if (!empty($_SESSION['logged_in'])) {
  header( "Content-Disposition: attachment; filename="The Name You Want Your Users To See.mp3"");
  header( "X-LIGHTTPD-send-file: /full/path/to/your/file.mp3");
} else {
  echo "Sorry, You're not on the list, You're not coming in!";
}

?>

If you’re using Lighttpd version 1.5 then you can replace “X-LIGHTTPD-send-file” with “X-Sendfile”.

PHP & Apache

Using X-Sendfile with Apache is very similar, however we need to turn X-Sendfile on. Either put “XSendFile On” in a .htaccess files where your script resides, or put this in your Apache config file. The php configuration is pretty much exactly like Lighttpd 1.5 handling:

<?php

if (!empty($_SESSION['logged_in'])) {
  header( "Content-Disposition: attachment; filename="The Name You Want Your Users To See.mp3"");
  header( "X-Sendfile: /full/path/to/your/file.mp3");
} else {
  echo "Sorry, You're not on the list, You're not coming in!";
}

?>

Feel free to move your files outside of the root path of the webserver which will prevent hotlinking, or as always, “deny from all” will do the trick in a .htaccess file.

Posted by voidet

Categorised under PHP
Bookmark the permalink or leave a trackback.

2 Comments

  1. Hello,

    Can the end of serving file by apache be notified back to a php or any loggin feature ?

    December 19, 2011 @ 8:39 am
    • VoiDeT

      Usually you would have it first check if they are logged in. Then with X-Sendfile header send out the file via apache.

      December 28, 2011 @ 9:09 am

One Trackback

  1. [...] This post was mentioned on Twitter by Richard S and Richard S, DevMoose. DevMoose said: Protecting Files Against Hotlinking with PHP, Lighttpd, Apache & X-Sendfile: I recently had to lock down some impo… http://bit.ly/d4kC4A [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

or