Hotlink protection in nginx, and what to allow
Stop other websites embedding your images with nginx valid_referers, without breaking direct visits, mail clients or your own other domains.
What hotlinking is
Hotlinking is another website putting your image on its page by pointing an <img> tag at your server. Their visitors see the picture. Your server sends it, and your bandwidth pays for it.
The browser gives you one thing to work with. When it fetches an image for a page, it usually sends a Referer header naming that page. Hotlink protection is a rule that looks at that header and refuses images asked for by pages on other sites.
The nginx rule
location ~* \.(png|jpe?g|gif|webp|avif|bmp)$ {
valid_referers none blocked server_names
shop.example *.shop.example;
if ($invalid_referer) {
return 403;
}
}
valid_referers lists the referrers that are fine. Anything else sets $invalid_referer, and the request gets a 403. The three keywords carry most of the meaning:
none: the request has noRefererheader at all.blocked: the header is there, and a proxy or firewall has stripped its value.server_names: the header names one of this site's own hostnames.
After those come any other hostnames you want to allow. A leading *. covers subdomains.
One practical warning. A location block matched by a regular expression takes those requests away from other blocks, so if your images already have a block that sets cache headers, put the two rules in the same block.
What to allow, and why
Requests with no Referer. Keep none and blocked. A request with no referrer is a person opening the image directly, a mail client showing your newsletter, or a browser with a privacy setting. Refusing those breaks the site for its own visitors, which is worse than the problem you set out to solve.
Your own other domains. A sister site, a shop on another domain, a landing page elsewhere. They are other websites as far as nginx can tell.
Services that show your images on your behalf. A newsletter service with a web version of each mailing is the usual one.
Then test it. A page on a site you have not allowed should get a 403, and a direct request should get the image:
curl -sI -e https://other.example/ https://example.com/photo.jpg
curl -sI https://example.com/photo.jpg
What it does not do
It is not access control. The Referer header is sent by the client, and a script can send any value it likes. Hotlink protection stops casual embedding. It does not stop somebody downloading the image and hosting a copy.
It also runs only on requests that reach nginx. If a CDN in front of the site has the image cached, the CDN may answer without asking your server, and your rule never sees the request. In that case set the same rule at the CDN.
And keep it to images. Applying a referrer rule to stylesheets, scripts or fonts causes breakage that is hard to trace, for very little saved bandwidth.
In KLYRN it is a rule on the site
Hotlink protection shipped in KLYRN 1.0.5, on each site's Rules tab. Switch it on and images asked for by a page on another website are refused with a 403. It covers PNG, JPEG, GIF, WebP, AVIF and BMP files.
What is still served matches the advice above: the site's own addresses, the websites you list, and anyone opening an image directly. You can list up to 20 other websites, and each one also covers its subdomains, so you type shop.example once.
The rule is written into the site's own nginx configuration. Like every configuration KLYRN renders, it is tested with nginx -t before it is loaded, so a mistake in a rule cannot take the web server down.