HttpSecureLinkModule Q?

Hi guys, I’m trying to configure secure link modulаr together with flv
streaming module but without success.

Can anyone give me an example with this basic setup.
location ~ .flv {

    root   /store;


    flv;


}

the plain url is http://127.0.0.1/subdir1/subdir2/movie.flv
subdir1/subdir2 are dynamic paths to files.
I wan;t to protect this path and flv file with temporary url.

Posted at Nginx Forum:

see excelent example in docs:
http://wiki.nginx.org/HttpSecureLinkModule

izrodix at 2010-12-21 6:44 wrote:

    flv;


}

the plain url is http://127.0.0.1/subdir1/subdir2/movie.flv
subdir1/subdir2 are dynamic paths to files.
I wan;t to protect this path and flv file with temporary url.

The secure link module protect file by md5. You should add a md5 string
in your url.

For example, the url is like this:

http://127.0.0.1/subdir1/subdir2/movie.flv?md5=NF0H4o7SIxt_vNa9XzzxzQ==

your configuration should be:

location ~ \.flv {
    secure_link $arg_md5;

secure_link_md5 your_secret_word$uri;

if ($secure_link = “”) {
return 403;
}

    root   /store;

    flv;
}

The md5 hash value of “your_secret_word$uri” will compare with the
string specified by “secure_link”. If the result is the same, the
variable of $secure_link is ‘1’, else it’s null string.

Posted at Nginx Forum:
HttpSecureLinkModule Q?


nginx mailing list
[email protected]
nginx Info Page


Weibin Y.

Thanks, for the replies but when i test this configuration users
continue to download files from this url
http://127.0.0.1/subdir1/subdir2/movie.flv” without problem.
Nginx doesn’t return 403;

location ~ .flv {
secure_link $arg_md5;
secure_link_md5 your_secret_word$uri;

if ($secure_link = “”) {
return 403;
}

root /store;

flv;
}

nginx-0.8.54 from freebsd ports.

/usr/local/etc/rc.d/nginx configtest
Performing sanity check on nginx configuration:
the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
configuration file /usr/local/etc/nginx/nginx.conf test is successful

_OPTIONS_READ=nginx-0.8.54
WITHOUT_DEBUG=true
WITHOUT_DEBUGLOG=true
WITH_FILE_AIO=true
WITH_IPV6=true
WITHOUT_GOOGLE_PERFTOOLS=true
WITH_HTTP_MODULE=true
WITH_HTTP_ADDITION_MODULE=true
WITH_HTTP_CACHE_MODULE=true
WITHOUT_HTTP_DAV_MODULE=true
WITH_HTTP_FLV_MODULE=true
WITHOUT_HTTP_GEOIP_MODULE=true
WITH_HTTP_GZIP_STATIC_MODULE=true
WITHOUT_HTTP_IMAGE_FILTER_MODULE=true
WITHOUT_HTTP_PERL_MODULE=true
WITHOUT_HTTP_RANDOM_INDEX_MODULE=true
WITH_HTTP_REALIP_MODULE=true
WITH_HTTP_REWRITE_MODULE=true
WITH_HTTP_SECURE_LINK_MODULE=true
WITH_HTTP_SSL_MODULE=true
WITH_HTTP_STATUS_MODULE=true
WITHOUT_HTTP_SUB_MODULE=true
WITHOUT_HTTP_XSLT_MODULE=true
WITHOUT_MAIL_MODULE=true
WITHOUT_MAIL_IMAP_MODULE=true
WITHOUT_MAIL_POP3_MODULE=true
WITHOUT_MAIL_SMTP_MODULE=true
WITHOUT_MAIL_SSL_MODULE=true
WITH_WWW=true
WITH_CACHE_PURGE_MODULE=true
WITHOUT_ECHO_MODULE=true
WITH_HEADERS_MORE_MODULE=true
WITH_HTTP_ACCEPT_LANGUAGE=true
WITHOUT_HTTP_ACCESSKEY_MODULE=true
WITHOUT_HTTP_AUTH_PAM_MODULE=true
WITHOUT_HTTP_AUTH_REQ_MODULE=true
WITHOUT_HTTP_EVAL_MODULE=true
WITH_HTTP_FANCYINDEX_MODULE=true
WITHOUT_HTTP_GUNZIP_FILTER=true
WITHOUT_HTTP_MOGILEFS_MODULE=true
WITH_HTTP_MP4_H264_MODULE=true
WITH_HTTP_NOTICE_MODULE=true
WITHOUT_HTTP_PUSH_MODULE=true
WITHOUT_HTTP_REDIS_MODULE=true
WITHOUT_HTTP_RESPONSE_MODULE=true
WITHOUT_HTTP_UPLOAD_MODULE=true
WITHOUT_HTTP_UPLOAD_PROGRESS=true
WITH_HTTP_UPSTREAM_FAIR=true
WITH_HTTP_UPSTREAM_HASH=true
WITH_HTTP_UPSTREAM_KEEPALIVE=true
WITHOUT_HTTP_ZIP_MODULE=true
WITHOUT_MEMC_MODULE=true
WITHOUT_PASSENGER_MODULE=true
WITHOUT_SLOWFS_CACHE_MODULE=true
WITHOUT_SUPERVISORD_MODULE=true
WITHOUT_SYSLOG_SUPPORT=true
WITH_UDPLOG_MODULE=true

Posted at Nginx Forum:

izrodix at 2010-12-21 16:49 wrote:

Thanks, for the replies but when i test this configuration users
continue to download files from this url
http://127.0.0.1/subdir1/subdir2/movie.flv” without problem.
Nginx doesn’t return 403;

Are you sure the request is processed in this location? Could you show
the debug log? (Debugging | NGINX)

Meanwhile, you can config nginx like this:

location ~ .flv {
secure_link $arg_md5;
secure_link_md5 your_secret_word$uri;

if ($arg_md5 = “”) {
return 403;
}

if ($secure_link = “”) {
return 403;
}

root /store;

flv;
}

flv;
WITHOUT_DEBUG=true
WITH_HTTP_GZIP_STATIC_MODULE=true
WITHOUT_MAIL_MODULE=true
WITHOUT_HTTP_AUTH_PAM_MODULE=true
WITHOUT_HTTP_UPLOAD_MODULE=true
WITH_UDPLOG_MODULE=true

Posted at Nginx Forum:
Re: HttpSecureLinkModule Q?


nginx mailing list
[email protected]
nginx Info Page


Weibin Y.

Add expire_time in security link.
http://wiki.nginx.org/HttpSecureLinkModule:
secure_link
syntax: secure_link $md5_hash[,$expire_time]
This directive specifies the MD5 hash value and the expired time of this
link URL’s. The $md5_hash should be encoded by modified Base64 for URL.
The $expired_time is the seconds since 1970-01-01 00:00:00 UTC. If you
did not add the $expire_time, then the link URL will never be expired.

Weibin Y.,
it’s working but may be I’m doing something wrong.
Here is what I do.

$uri_hash = md5(‘your_secret_word’.‘/subdir1/subdir2/movie.flv’, true);
$uri_ehash = base64_encode($uri_hash);

this is result of uri_ehash
http://127.0.0.1/subdir1/subdir2/movie.flv?md5=F96syvsfhvPq54ME2VEX4A==

this show me err 403
http://127.0.0.1/subdir1/subdir2/movie.flv

I delete some part of hash

download is complete

  1. F96syvsfhvPq54ME2VEX4A==

download is complete
2. F96syvsfhvPq54ME2VEX4A=

download is complete
3. F96syvsfhvPq54ME2VEX4A

this show me err 403
4.F96syvsfhvPq54ME2VEX4

Is this right ?

Posted at Nginx Forum:

izrodix at 2010-12-21 19:28 wrote:

this show me err 403
download is complete
3. F96syvsfhvPq54ME2VEX4A

this show me err 403
4.F96syvsfhvPq54ME2VEX4

Is this right ?

Yes, you are right.

The character of ‘=’ in the base64 code is the padding character, it’s
meaningless but for pad. So if you delete the ‘=’, it’s the same string.
see this url for detail: Base64 - Wikipedia

The base64 encode should be base64 for
url(Base64 - Wikipedia). It means no
padding ‘=’ will be used and the characters of ‘+’ and ‘/’ in the base64
string should be respectively replace by ‘-’ and ‘_’. I don’t know if
there is a function like base64_encode_url() for this encode
transformation. You can find it or try it manually.

By the way, the string of ‘your_secret_word’ should be your own secret
string. It’s used to protect anyone can’t guess the transformation
procedure of md5 hash.

Posted at Nginx Forum:
Re: HttpSecureLinkModule Q?


nginx mailing list
[email protected]
nginx Info Page


Weibin Y.

On 22 Dez 2010 02h25 WET, [email protected] wrote:

izrodix at 2010-12-21 19:28 wrote:

Weibin Y.,
it’s working but may be I’m doing something wrong.
Here is what I do.

$uri_hash = md5(‘your_secret_word’.’/subdir1/subdir2/movie.flv’,true);
^^^^
This is incorrect. You need the string not the raw binary format.

$uri_ehash = base64_encode($uri_hash);

Use this instead:

$uri_hash = md5(‘your_secret_word’ . ‘/subdir1/subdir2/movie.flv’);
$uri_ehash = str_replace(’=’, ‘’, strtr(base64_encode($uri_hash), ‘+/’,
‘-_’)));

— appa

I’ve updated the Wiki:
http://wiki.nginx.org/HttpSecureLinkModule#For_Nginx_version_.E2.89.A5_0.8.50_-_better_handling_of_the_MD5_hash_and_adding_expiration_time

based on the discussion on this thread. Please verify it.

Thanks,
— appa

António P. P. Almeida at 2010-12-22 13:53 wrote:

I’ve updated the Wiki:

http://wiki.nginx.org/HttpSecureLinkModule#For_Nginx_version_.E2.89.A5_0.8.50_-_better_handling_of_the_MD5_hash_and_adding_expiration_time

based on the discussion on this thread. Please verify it.

I think you should add the expiration time in another argument like
this:
http://example.com/p/file/top_secret.pdf?st=vXjVzvGW4363YG1I6vb11A&e=13245277231161

It seems that the new secure link module(above Nginx-0.8.50) uses the
raw binary format MD5 instead. And the php CLI is like this:
php -r ‘print str_replace(“=”, “”,
strtr(base64_encode(md5(“segredo/p/files/top_secret.pdf13245277231161”,
true)), “+/”, “-_”)) . “\n”;’

And the configuration (have not tested yet):

location /p/ {
secure_link $arg_st,$arg_e; # this must match the URI part related
to the MD5 hash and expiration
secure_link_md5 segredo$uri$arg_e; # this is how the MD5 hash is
built from a secret token and an URI

## If the hash is incorrect then $secure_link is a null string.
if ($secure_link = "") {
    return 403;
}

## The current local time is greater than the specified expiration 

time.
if ($secure_link = “0”) {
return 403;
}

## If everything is ok $secure_link is 1.
## This needs to be here otherwise you'll get a 404.
rewrite ^/p/(.*)$ /p/$1 break;

}

Thanks,
— appa


nginx mailing list
[email protected]
nginx Info Page


Weibin Y.

On 22 Dez 2010 06h56 WET, [email protected] wrote:

António P. P. Almeida at 2010-12-22 13:53 wrote:

I’ve updated the Wiki:

http://wiki.nginx.org/HttpSecureLinkModule#For_Nginx_version_.E2.89.A5_0.8.50_-_better_handling_of_the_MD5_hash_and_adding_expiration_time

based on the discussion on this thread. Please verify it.

I think you should add the expiration time in another argument like
this:

http://example.com/p/file/top_secret.pdf?st=vXjVzvGW4363YG1I6vb11A&e=13245277231161

It seems that the new secure link module(above Nginx-0.8.50) uses
the raw binary format MD5 instead. And the php CLI is like this: php
-r ‘print str_replace(“=”, “”,
strtr(base64_encode(md5(“segredo/p/files/top_secret.pdf13245277231161”,
true)), “+/”, “-_”)) . “\n”;’

Yes. This differs from when using secure_link_secret, that uses the
string
form of the MD5 hash.

return 403;
rewrite ^/p/(.*)$ /p/$1 break;
}

Done.

Thanks,
— appa

Hi,

may i suggest to do it like mod_secdownload from lighttpd? Instead of
re-inventing
the wheel you would also have compatibility which could/would make it
easier to
switch.

The URL are in form of:
$prefix/$hash/$timestamp/$path/to/file

$prefix can be anything to seperate different secret areas
$hash is a md5hash from $secret$file$timestamp
$timestamp is a unixtimestamp in hex
$path/to/file is the complete path with file you want to request

On the server side you have to set variables like the expiration time,
the secret
and maybe the “real” path per location if you not want to have the files
stored
inside root to be sure that it cannot be requested by accident.

On the Serverside you would have to do the following:
parse the url for $prefix/$hash/$timestamp/$path/to/file, convert the
timestamp
from hex back to unixtime and check if $unixtimestamp+$timeout <
$timenow,
otherwise return 410 (gone). If not, check if provided md5hash matches
local
generated hash with $secret$file$timestamp where $timestamp is used from
the
requst (since this provides you the timestamp when the url was
generated).

This would make clear urls (no uuencoding etc.), having expiration time,
and
compatibility to “other well known solution”. Having lighty beside nginx
would
be no problem and you could use well known code / modules for other cms
systems
etc. which already support mod_secdownload.

But thats just my 2 cents…

Regards,
Sven

Am 22.12.2010 07:56, schrieb Weibin Y.:

On 22 Dez 2010 06h56 WET, [email protected] wrote:

if ($secure_link = “”) {

This needs to be here otherwise you’ll get a 404.

rewrite ^/p/(.*)$ /p/$1 break;
}

I just tested it. It works.

— appa

Thanks Guys for the replies,
this configuration works for me.

location ~ ^/vstore/(?[\w\-=]+,\d+)(?/.*\.mp4)$ {
    secure_link $secure;
    secure_link_md5 $secure_link_expires.$file.SECRET;

    if ($secure_link = "") {
            return 403;
    }

    if ($secure_link = 0) {
            return 410;
    }

    alias /store$file;
    mp4;
}

$secret_word = “SECRET”;
$uri_prefix = “http://127.0.0.1/vstore/”;
$file = ‘/subdir1/subdir2/file.mp4’;
$time = time()+600;
$secret = md5($time.‘.’.$file.‘.’.$secret_word, true);
$secret = strtr(base64_encode($secret), ‘+/’, ‘-_’);

echo $hash_url = $uri_prefix.$secret.‘,’.$time.$file;

Posted at Nginx Forum: