2

front-end web developer here. Sorry in advance.

My company wants to store new builds of our software on our web server, running Nginx, provided by WP Engine.

The file path for these builds would be company.com/downloads/file.zip. We want to restrict access to files in this folder unless they come from a specific referring URL that sits behind a login gate for our customers.

  • If user clicks link to any file inside /downloads/ from allowed referrer, user gets file
  • If user clicks link from any other source, return 404 or redirect to homepage
  • If empty referrer or direct access attempt, return 404 or redirect to homepage

I've found a resource on preventing hotlinking for images (we'll be dealing with .zip files), which might work for me, but I need help with the syntax of this language. There's probably a bunch wrong with it.

location ~ /downloads/$ {
valid_referers none blocked ~.allowed_domain.com;
if ($invalid_referer) {
return 404;
}
}

WP Engine doesn't allow me to add Nginx code myself, so I'll have to send them the code I want them to implement. If anyone knows how to do this and can help me out, I'd really appreciate it!

Jesse Rogers
  • 131
  • 1
  • 6
  • Why? There are already WordPress plugins to handle hotlink protection. Getting into nginx config for this seems excessive. – Michael Hampton Feb 22 '17 at 18:20
  • I've looked for plugins, but found very few which were all poorly reviewed. But I did find this one, which might work: https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/ – Jesse Rogers Feb 22 '17 at 18:28

2 Answers2

2

Other possibility is to use X-Accel header. I don't know your use case, so it may not be a good fit.

X-Accel is nginx specific header. You can issue that header in your PHP script - like header("X-Accel-Redirect: /private-downloads/magic.iso") When nginx recognize this header, it will server content of the file magic.iso located in /data/private-downloads.

So your task is to prepare download.php which check authorization and respond either with X-Accel header or redirect to login screen.

Definition of /private-downloads/ in nginx.conf

location /private-downloads/ {
    internal;    # this
    alias /data/private-downloads;
    # this should be located outside of HTTP server root
}

For more details, plase check x-accel questions on serverfault. 1

Věroš K.
  • 500
  • 3
  • 9
  • Oh, does this solution require me to be able to put a directory outside of `public_html`? Because WP Engine won't let me do that, which is super frustrating. – Jesse Rogers Feb 23 '17 at 00:37
  • You can put the secret directory inside `public_html` but it is not recommended technique. At least, try to use subdirectory name which is hard to guess. – Věroš K. Feb 23 '17 at 10:25
  • Gotcha. And do I need to add that Nginx code you included in this answer as well? Or is that just additional info? – Jesse Rogers Feb 23 '17 at 16:46
  • If you don't use internal alias, you may not omit `location` internal statement. But I'm not sure on this area. I would stick with `/private-downloads/` internal alias pointing to HTML root. It can save you some work later. (e.g. if you move to another hosting, name of your secret sudirectory will be exposed, ...) – Věroš K. Feb 24 '17 at 11:09
  • There is a big typo in previous comment. There should be **You probably may omit** – Věroš K. Feb 24 '17 at 15:58
  • My company ended up finding another solution that didn't require use of our Nginx server. But I did all the reading you linked me to, and I can clearly see that you gave me the right answer that would have worked had I been able to implement it. Thank you for you help, I really appreciate it! – Jesse Rogers Feb 24 '17 at 17:30
0

You can use valid_referers nginx directive. ( nginx doc )

location /downloads/ {
    alias /var/www/downloads;
    valid_referers  www.example.me ;

if ($invalid_referer) {
        return 404;
    }
}

I personally never tried this in production, because I prefer to use X-Accel header . You can verify your user in PHP script and then send nginx header X-accel. The header will ask nginx to server the static files by nginx.

Věroš K.
  • 500
  • 3
  • 9
  • Thanks for the answer. I'll definitely shoot this over to them and give it a shot on a staging server. How can I use X-Accel header? Sorry, probably a stupid question, but if it's a better solution and a valid option for me, I'd like that. – Jesse Rogers Feb 22 '17 at 20:33
  • I've been doing a lot of reading on this, and I can't figure out why this answer didn't work. Granted, I had WP Engine implement it for me so I can't verify that it was done correctly. In your other answer, you mentioned that I can X-Accel through PHP? That might be the best option for me. I'll give that a shot. – Jesse Rogers Feb 23 '17 at 00:34