Starting from version 0.8.50 in Nginx secure_link module there has been a significant improvement in protecting links from counterfeiting. Oddly enough, the new features are still not reflected in the official documentation [
1 ]. The description in English can be found on the Nginx Community site [
2 ], as well as Sysoev’s explanations regarding these changes [
3 ]. PHP code for generating secure links can be found in the nginx forum [
4 ].
In general, the innovation looks like this:
nginx.conf:
location ~ ^ / p / (? <secure> [\ w -] +, \ d +) / (? <secured_stuff>. +) $ {
secure_link $ secure;
# in this example '$ secure' = "HASH, TIMESTAMP"
secure_link_md5 PASSWORD $ secure_link_expires $ secured_stuff;
# '$ secure_link_expires' is a nginx variable containing the value after the comma from 'secure_link' = TIMESTAMP
if ($ secure_link = "") {return 403; } # invalid link
if ($ secure_link == 0) {return 410; } # expired link
# link is ok, do something here
}
The URL might look like: / p / HASH, TIMESTAMP / ANYTHING where
PASSWORD secret password
TIMESTAMP is the time to which the link in unix epoch is valid.
ANYTHING arbitrary text
Base64-URL-encoded HASH [
5 ] md5 hash from the secure_link_md5 template ($ secured_stuff = ANYTHING in this example). The characters '=' after base64 can be omitted
')
Nginx has a couple of implicit nuances in md5 sum calculation:
1. the string to be counted from the URL ($ secured_stuff) is decoded from the URL encoding to the original view
2. md5 hash should be transmitted in binary format for encoding to base64
PHP code can be like this:
$time = time() + EXPIRE_TTL;
Arguments and cookies can also be used to transfer hash and time:
for a URL like
http://example.com/p/files/top_secret.pdf?st=PIrEk4JX5gJPTGmvqJG41g&e=1324527723
where the argument
st is a hash of PASSWORD, the URI and the argument
elocation views
location / p / {
secure_link $ arg_st, $ arg_e; # this must match the URI part related
secure_link_md5 PASSWORD $ uri $ arg_e; # PASSWORD is the secret token
....
}
As it is not difficult to guess, you can use the client’s IP address when generating the hash.
References:
[1]
sysoev.ru/nginx/docs/http/ngx_http_secure_link_module.html[2]
wiki.nginx.org/HttpSecureLinkModule[3]
nginx.org/pipermail/nginx/2010-September/022324.html[4]
forum.nginx.org/read.php?21 , 126363,128324 # msg-128324
[5]
en.wikipedia.org/wiki/Base64#URL_applications