Monday, October 12, 2020

Securing Download URLs in NGINX

 

Securing Download URLs in NGINX

NGINX is secure and reliable as web servers, reverse proxies, and caches for content.

For additional protection against access by unauthorized clients, we can use directives from the ngx_http_secure_download_module to require that clients include a specific hashed string in the URL of the asset they are requesting.

ngx_http_secure_download_module 

A module that enables you to create links which are only valid until a certain datetime is reached.

The way it works is similar to lightttpd’s mod_secdownload, but not exactly same.


  • Available directories under this module
            -> secure_download
                    Enabling secure download.
                    secure_download [ on | off ]

            -> secure_download_secret
                 Defines the string which is included in the md5 hash. It can also contain variables.
                 secure_download_secret  <secret string>

             -> secure_download_path_mode
This defines if the md5 hash has to be done for the full path, including filename, or just the folders which contain the file, without the filename. 
Depending on this your link will be valid either for a whole directory, or only for one file.
secure_download_path_mode [ file | folder ]

  • Variables used in this module
               -> $secure_download 

This variable contains the result of the request URL validation process. It always contains a number and can have the following possible values:
  • >0 : link is valid and the value is the amount of seconds until it expires
  • -1  : the timestamp is expired
  • -2  : the md5 hash is wrong
  • -3  : other problem like f.e. parsing problem or module config problem

Generating Secure URIs

A generated URI must have the following format:

<real_path> / <md5_hash> / <expiration_timestamp>


The <md5 hash> gets generated out of the following string:

<real_path> / <secret> / <expiration_timestamp>

  • real_path can be either the path of the file which you want to access or the folder which contains the file, which of those two has to be defined in the NGINX config
  • secret is some random string which must be known by the NGINX config and by the link generating script
  • expiration_timestamp is a unix_timestamp (seconds since beginning of 1970) in hexadecimal format

Example:

Lets assume expiration time stamp is 1240928342. Convert this to Hexadecimal which is 49F71056.

Lets assume secret string configured in NGINX is "privatestring" and real_path is plus_archives/xyz/abc/2019.zip

Now we can generate md5_hash by input /plus_archives/xyz/abc/2019.zip/privatestring/49F71056  which is 82dc1278c04c69f80f40262771a17136.

Using above now our valid URI is  /plus_archives/xyz/abc/2019.zip/82dc1278c04c69f80f40262771a17136/49F71056

Corresponding nginx configuration will be:

location /pro_plus_archives {
    secure_download on;
    secure_download_secret privatestring;
    secure_download_path_mode file;

    if ($secure_download = "-1") {
        return 468;
    }
    if ($secure_download = "-2") {
        return 467;
    }
    if ($secure_download = "-3") {
        return 500;
    }

rewrite ^/plus_archives/(.*)/[0-9a-zA-Z]*/[0-9a-zA-Z]*$ $1; proxy_pass http://192.168l.10.34:8380/plus-archives/$1; break;
}

Note: This rewrite will remove  /pro_plus_archives/ and <md5_hash> / <expiration_timestamp> from the URI and save to $1 then proxypass to LDC by appending $1, if and only  the URI is valid ($secure_download = 0).

No comments:

Post a Comment