Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support NGINX $host in Downloads hotlink protection #4011

Merged
merged 1 commit into from
Jul 2, 2020
Merged

Support NGINX $host in Downloads hotlink protection #4011

merged 1 commit into from
Jul 2, 2020

Conversation

Deltik
Copy link
Member

@Deltik Deltik commented Nov 5, 2019

Fixes: #4010
Related: #3111

Problem

If there are two download mirrors, slow.example.com and fast.example.com, hotlink protection using an NGINX secure_link_md5 expression in the Downloads plugin cannot distinguish between these hostnames.

This means that a user limited to slow.example.com can change the download host to fast.example.com and download from the better mirror.

Solution

To solve this, NginxSecureLinkMd5Decorator needs to support the NGINX $host variable. Having this variable in the expression will lock down the secure link to the specific download host.

Updated Documentation

Configure e107

Ideally, both e107 and NGINX should be configured at the exact same time, but e107 may be configured first because doing so would minimize the chance of disruption to downloaders, since the NGINX secure_link_md5 URL protection mode merely appends query string arguments to the download URL.

  1. Navigate to /e107_plugins/download/admin_download.php?mode=main&action=settings in your web browser.
  2. Click on the Protection tab.
  3. Select NGINX secure_link_md5 as the URL protection mode
  4. Type in your secure_link_md5 expression into the NGINX secure_link_md5 expression field. This is the same expression that you put into your NGINX configuration (see the section below).
  5. In the Duration of validity in seconds field, enter a whole number for how long in seconds you want each generated download link to live after the link is generated.
  6. Click the green Update Options button.

Now, all downloads will have md5 appended as a query parameter, generated from the expression you put in. If the expression contains $secure_link_expires, expires will be appended as a query parameter as well.

Configure your NGINX download server

Set up your NGINX download location config with secure_link_md5 to protect your downloads. For an example of how to do this, see the Using Secured URLs that Expire section of this blog post from NGINX.

This is a sample secure_link_md5 expression:

$secure_link_expires$uri$remote_addr$host secret
  • $secure_link_expires enables the expiration of links generated by the e107 Downloads plugin.
  • $uri matches the download path intended to be protected.
  • $remote_addr ensures that only the client's IP address may be used to download the file.
  • $host ensures that the token can only be used for a specific virtual host (such as fast.example.com).
  • secret is a string known only to e107 and your NGINX config so that your users/downloaders cannot generate their own secure links.

If your secure_link_md5 expression contains $secure_link_expires, the secure_link directive should read secure_link $arg_md5,$arg_expires; like in this example server block:

server {
    listen 80;
        server_name secure-link-demo;

        location /files {
            root /var/www;
            secure_link $arg_md5,$arg_expires;
            secure_link_md5 "$secure_link_expires$uri$remote_addr secret";

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

If your secure_link_md5 expression does not contain $secure_link_expires, the secure_link directive should read secure_link $arg_md5; like in this example server block:

server {
    listen 80;
        server_name secure-link-demo;

        location /files {
            root /var/www;
            secure_link $arg_md5;
            secure_link_md5 "$uri$remote_addr secret";

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

If you have multiple virtual hosts and want to ensure that the secure link token cannot be used on a different hostname (e.g. prevent the client from changing slow.example.com to fast.example.com for a better download mirror), add the $host variable to the secure_link_md5 expression like this:

server {
    listen 80;
        server_name slow.example.com;
        limit_rate 50k;

        location /files {
            root /var/www;
            secure_link $arg_md5,$arg_expires;
            secure_link_md5 "$secure_link_expires$uri$remote_addr$host secret";

            if ($secure_link = "") { return 403; }
            if ($secure_link = "0") { return 410; }
        }
}
server {
    listen 80;
        server_name fast.example.com;

        location /files {
            root /var/www;
            secure_link $arg_md5,$arg_expires;
            secure_link_md5 "$secure_link_expires$uri$remote_addr$host secret";

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

Fixes: #4010
Related: #3111

==== Problem ====
If there are two download mirrors, `slow.example.com` and
`fast.example.com`, hotlink protection using an NGINX `secure_link_md5`
expression in the Downloads plugin cannot distinguish between these
hostnames.

This means that a user limited to `slow.example.com` can change the
download host to `fast.example.com` and download from the better mirror.

==== Solution ====
To solve this, `NginxSecureLinkMd5Decorator` needs to support the NGINX
`$host` variable.  Having this variable in the expression will lock down
the secure link to the specific download host.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add $host variable support to Downloads » Protection » NGINX secure_link_md5
2 participants