lighttpd 1.4.x
https://www.lighttpd.net/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.7 KiB
147 lines
3.7 KiB
=========================== |
|
Secure and Fast Downloading |
|
=========================== |
|
|
|
----------------------- |
|
Module: mod_secdownload |
|
----------------------- |
|
|
|
:Author: Jan Kneschke |
|
:Date: $Date: 2004/08/01 07:01:29 $ |
|
:Revision: $Revision: 1.1 $ |
|
|
|
:abstract: |
|
authenticated file requests and a countermeasure against |
|
deep-linking can be achieved easily by using mod_secdownload |
|
|
|
.. meta:: |
|
:keywords: lighttpd, secure, fast, downloads |
|
|
|
.. contents:: Table of Contents |
|
|
|
Options |
|
======= |
|
|
|
:: |
|
|
|
secdownload.secret = <string> |
|
secdownload.document-root = <string> |
|
secdownload.uri-prefix = <string> (default: /) |
|
secdownload.timeout = <short> (default: 60 seconds) |
|
|
|
Description |
|
=========== |
|
|
|
there are multiple ways to handle secured download mechanisms: |
|
|
|
1. use the webserver and the internal HTTP authentication |
|
2. use the application to authenticate and send the file |
|
through the application |
|
|
|
Both ways have limitations: |
|
|
|
webserver: |
|
|
|
- ``+`` fast download |
|
- ``+`` no additional system load |
|
- ``-`` inflexible authentication handling |
|
|
|
application: |
|
|
|
- ``+`` integrated into the overall layout |
|
- ``+`` very flexible permission management |
|
- ``-`` the download occupies an application thread/process |
|
|
|
A simple way to combine the two ways could be: |
|
|
|
1. app authenticates user and checks permissions to |
|
download the file. |
|
2. app redirects user to the file accessible by the webserver |
|
for further downloading. |
|
3. the webserver transfers the file to the user. |
|
|
|
As the webserver doesn't know anything about the permissions |
|
used in the app, the resulting URL would be available to every |
|
user who knows the URL. |
|
|
|
mod_secdownload removes this problem by introducing a way to |
|
authenticate a URL for a specified time. The application has |
|
to generate a token and a timestamp which are checked by the |
|
webserver before it allows the file to be downloaded by the |
|
webserver. |
|
|
|
The generated URL has to have the format: |
|
|
|
<uri-prefix><token>/<timestamp-in-hex><rel-path> |
|
|
|
<token> is an MD5 of |
|
|
|
1. a secret string (user supplied) |
|
2. <rel-path> (starts with /) |
|
3. <timestamp-in-hex> |
|
|
|
|
|
As you can see, the token is not bound to the user at all. The |
|
only limiting factor is the timestamp which is used to |
|
invalidate the URL after a given timeout (secdownload.timeout). |
|
|
|
.. Note:: |
|
Be sure to choose a another secret than the one used in the |
|
examples, as this is the only part of the token that is not |
|
known to the user. |
|
|
|
|
|
|
|
If the user tries to fake the URL by choosing a random token, |
|
status 403 'Forbidden' will be sent out. |
|
|
|
If the timeout is reached, status 408 'Request Timeout' will be |
|
sent. (This does not really conform to the standard, but should |
|
do the trick). |
|
|
|
If token and timeout are valid, the <rel-path> is appended to |
|
the configured (secdownload.document-root) and passed to the |
|
normal internal file transfer functionality. This might lead to |
|
status 200 or 404. |
|
|
|
Example |
|
======= |
|
|
|
Application |
|
----------- |
|
|
|
Your application has to generate the correct URLs. The following sample |
|
code for PHP should be easily adaptable to any other language: :: |
|
|
|
<?php |
|
|
|
$secret = "verysecret"; |
|
$uri_prefix = "/dl/"; |
|
|
|
# filename |
|
$f = "/secret-file.txt"; |
|
|
|
# current timestamp |
|
$t = time(); |
|
|
|
$t_hex = sprintf("%08x", $t); |
|
$m = md5($secret.$f.$t_hex); |
|
|
|
# generate link |
|
printf('<a href="%s%s/%s%s">%s</a>', |
|
$uri_prefix, $m, $t_hex, $f, $f); |
|
?> |
|
|
|
Webserver |
|
--------- |
|
|
|
The server has to be configured in the same way. The URI prefix and |
|
secret have to match: :: |
|
|
|
server.modules = ( ..., "mod_secdownload", ... ) |
|
|
|
secdownload.secret = "verysecret" |
|
secdownload.document-root = "/home/www/servers/download-area/" |
|
secdownload.uri-prefix = "/dl/" |
|
secdownload.timeout = 120 |
|
secdownload.algorithm = "md5"
|
|
|