Can I forbid download from external links?

Hi,

I searched but couldn’t find any topic about this.

I want to disable download from external links, that is, I’m not going to limit the download privilege to registered users, I’m OK for anybody to download the resources on my Discourse site, but I would like them to at least visit the site and see the topic.

Currently, if there’s some file uploaded on Discourse, somebody can just post the link to the file somewhere and people can download it without even know it’s coming from my site, is there anyway to achieve this?

Thanks a lot.
Jian

2 Likes

Perhaps this does help?

3 Likes

Thanks for replying.

No this is a different scenario, it restrict any un-logged-in user from downloading, what I’m trying to get is to prevent downloading from a link to the local resource from other website, For people visiting my site, they can download whether registered or not.

1 Like

Those are semantically the same thing?

You can only secure media or not. If not secured surely anyone can use the link without bringing up your UI? The browser won’t care what pages it has visited prior.

If the resources are valuable, why not secure them and distribute the link to the topic they are linked in. This will provide an additional incentive to register with your site?

1 Like

The browser won’t, the server can. By default, when a browser makes a request to the same origin as the page with the reference, it will include a referrer header to tell the server where it came from. A server can use this information to influence behaviour, including allowing/denying access to certain locations.

It’s easy to circumvent but it prevents casual linking from other websites.

location /uploads/ {
    valid_referers  www.example.com;
    if ($invalid_referer) {
        return 403;
    }
}

Replacing www.example.com in the above code with the domain of your Discourse instance should be appropriate nginx config to prevent hotlinking to the uploads on your instance.

You may also want to do something different than return 403, (not allowed) for example you may want to redirect to your Discourse home page. To do that, you could use the following code instead.

location /uploads/ {
    valid_referers  www.example.com;
    if ($invalid_referer) {
        return 307 /;
    }
}

It should be possible to add something to your app.yml file to inject the config during a rebuild. That part I’m not sure how to do though, I haven’t looked into it in any great detail.

4 Likes

And that’s probably good enough? Touché Simon, excellent.

Even better if you were to add a rule to redirect to the homepage?

3 Likes

Cheers, I did have a paragraph about redirecting but I’ve edited my previous post to make it clearer using a complete example.

1 Like

Thanks for sharing Simon. This could the solution for my requirements, though I still don’t know how to apply it with Discourse, I know a little about Linux server and Apache, but Discourse use Docker and Ngnix both of them are out of my knowledge range. But anyway Simon has told us a direction and I will look into it to see if I can do something.

1 Like

It turns out that the config Discourse uses for nginx includes something for hotlinking already, albeit commented out. So what you can do is add a couple of replaces to your app.yml file to uncomment those lines.

Edit /var/discourse/containers/app.yml with your preferred editor. At the end you’ll find a run section and at the end of that you’ll find an exec to echo “end of custom commands”.

Before that exec, add the following lines:

  - replace:
      filename: "/etc/nginx/conf.d/discourse.conf"
      from: "#valid_referers none blocked mysite.com *.mysite.com;"
      to: valid_referers none blocked mysite.com *.mysite.com;

  - replace:
      filename: "/etc/nginx/conf.d/discourse.conf"
      from: "#if ($invalid_referer) { return 403; }"
      to: if ($invalid_referer) { return 307 /; }

In the first replace section you’ll see the “to:” line with mysite.com *.mysite.com, substitute those for your own domain name, e.g. discourse.org *.discourse.org. The second replace assumes that you want visitors to be redirected to the Discourse home page.

After saving the changes, run the following commands to rebuild Discourse with the updated nginx config.

cd /var/discourse
./launcher rebuild app
4 Likes