3

This set of rules causes the nolinks.jpg image to appear if anyone tries to link directly to an image from a remote site. It is working well but with the latest Firefox, the browser is forced to https rather than http. How can it be made to work whether https, http? I rarely use regular expressions so not sure how to apply them here.

# Block external links
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?domain1\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?domain1\.net/ [NC]
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?domain1\.org/ [NC]
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?domain2\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?domain2\.net/ [NC]
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?domain2\.org/ [NC]
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?devdomain\.dev/ [NC]

RewriteCond %{HTTP_REFERER} !^$
RewriteRule show_image\.php http://www.domain1.com/nolinks.jpg? [R=301,QSA]

If forced to https, the image would have to link to https too. Also, it needs to work whether www or no www. How is this done?

5
  • 2
    Do you have any other directives in your .htaccess file?
    – MrWhite
    Jan 15 at 10:30
  • Just a few basic things like AddType and ErrorDocument but no other rewrite-related directives.
    – DonP
    Jan 16 at 21:49
  • "the browser seems to get stuck trying and keeps going to https rather than http" - What do you mean exactly by this? Are you seeing a 3xx redirect in the network traffic (in the browser)? Is your site accessible on HTTPS?
    – MrWhite
    Jan 19 at 19:24
  • 2
    it is likely caused by HTTPS-only mode which was introduced in FF 83. Does your site support HTTPS? If not, you probably need to add HTTPS support to fix this issue. Jan 20 at 11:23
  • I know that it's caused by the Firefox change (which is ridiculous) but I can't tell every site visitor to disable it so the .htaccess which is not working due to this change is what I am trying to fix. Fortunately the site is accessible by https but wouldn't have been a few months ago so the only real problem is my own .htaccess making none of the images show up.
    – DonP
    Jan 21 at 8:22
2

There's nothing in the directives you've posted that would cause this directly. Throwing a regex at this isn't going help. The RewriteRule directive you posted redirects to http - end of. So, any "redirect" to HTTPS is coming from somewhere else.

You need to examine the HTTP request/response headers in the browser. Are you actually seeing a 3xx redirect or is the browser "upgrading" the request? Are you sending a Content-Security-Policy: upgrade-insecure-requests; HTTP response header? Or even Strict-Transport-Security header (although that is only relevant when sent over HTTPS). Have you dabbled with HSTS in the past?!

sometimes, especially with the latest Firefox

However, the fact that this appears to be intermittent and browser dependent would seem to suggest the problem is elsewhere and harder to debug.

Since the "big push" to HTTPS everywhere, it seems strange that any site would be hotlinking an HTTP image - this would cause problems if the source site is HTTPS. Maybe the source site is triggering the upgrade/redirect to HTTPS?!

However, there are some concerns with the directives as posted.

  1. There is no L flag on the RewriteRule, so processing is going to continue through the file and potentially be rewritten or redirected by later directives. In other words, there could be a conflict with other directives. However, you've stated that there are "no other rewrite-related directives" - so that would seem to rule out this possibility. Although it is the most likely one.

    [R=301,L]
    
  2. You've included the QSA flag on the RewriteRule and included a trailing ? on the substitution string (ie. /nolinks.jpg?). This is really a contradiction. The trailing ? effectively removes any query string from the original request, but the QSA flag appends it again! You would get the same result without the trailing ? and without the QSA flag, however, you do want to remove the query string. So, you should keep the trailing ? and remove the QSA flag. Or, use the QSD (Query String Discard) flag instead on Apache 2.4.

    RewriteRule show_image\.php http://www.domain1.com/nolinks.jpg [QSD,R=301,L]
    
  3. You are using a 301 (permanent) redirect. This reduces the hits to your server as the redirect response should be cached by the browser. However, it also means that if a user should visit a site that is hotlinking your images and they are redirected to nolinks.jpg then they will also be redirected when they visit your site and will be unable to see your images. You would need to change this to a 302 (temporary) redirect to avoid this behaviour - but maybe that's considered an edge case and you want to keep this "permanent". However, a "cached redirect" could perhaps

  4. You are redirecting to HTTP and checking HTTP in the Referer header in all your conditions. Are you not using HTTPS on any of your sites?!

  5. Instead of redirecting to another image, it would be far more efficient and less resource-intensive (part of the reason for creating a hotlink protection script in the first place) if you simply block (403 Forbidden) the request instead. For example:

    RewriteRule show_image\.php - [F]
    
  6. The use of RewriteCond %{HTTP_REFERER} !^$ is arguably necessary since some users might suppress the HTTP Referer and without this condition they would not be able to see your images. Although you could argue that the user knows what they are doing in this case and have made the intentioned decision that they may not see some images. However, this condition also allows a site that is hotlinking your images to set a Referrer-Policy that suppresses the Referer and overrides your hotlinking script!


UPDATE:

...caused by HTTPS-only mode which was introduced in FF 83 .... Fortunately the site is accessible by https ... so the only real problem is my own .htaccess making none of the images show up. ... the .htaccess rewrite rules to work whether http or https

Ah, in that case, as touched on in #4 above, you need to modify all instances of http in the RewriteCond directives to https? - the ? quantifier makes the s optional.

For example:

RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?domain1\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?domain1\.net/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?domain1\.org/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?domain2\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?domain2\.net/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?domain2\.org/ [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?devdomain\.dev/ [NC]

Whether you change the http (to https) in the RewriteRule substitution string is really up to you (if you are not forcing HTTPS on your site)¹:

RewriteRule show_image\.php https://www.domain1.com/nolinks.jpg? [R=301,L]

(NB: Just https, not https? in the substitution string.)

¹ But note that if you redirect to plain HTTP then any HTTPS site that hotlinks your image(s) - where the user is not using "HTTPS-only mode" in Fx (or similar plugin in other browsers) - will get a "mixed content" warning in their browser and the nolinks.jpg image won't display.

Or, simply block the request (preferable from a server perspective) as mentioned in #5 above:

RewriteRule show_image\.php - [F]
6
  • Thank you. Yes, I know it's nothing to do with the directives but the rewrite rule expects http rather than https so when it gets https as the browser is forcing it to do, it shows the nolinks.jpg image.
    – DonP
    Jan 21 at 8:18
  • 1
    The site is NOT https and was never designed to be. It is also a legacy site originally written on the mid-'90s and rewritten several times since but fortunately after recently changing hosting companies it will run as https. If run as https, the links.jpg could also be loaded that way but where I need the help is for the ,htaccess rewrite rules to work whether http or https. On the intermittent part, that may be due to cashing that it seems to sometimes work and not related to the problem. I know that this can be overridden so the rewrite is for "casual bandwidth thieves" rather than pros.
    – DonP
    Jan 21 at 8:29
  • 1
    I've updated my answer.
    – MrWhite
    Jan 21 at 10:12
  • That worked perfectly and was exactly what I was looking for! However, I now see that it works only when no www. How can I make it work whether www or not? (I’ll append this to my question too.)
    – DonP
    Jan 23 at 0:56
  • 1
    You mean when navigating your site with no www? HTTP or HTTPS or both? What happens exactly? The regex (.+\.)? should already handle this situation (in fact, it allows any subdomain). Make sure you are not seeing a cached response - since this is a 301 (permanent) redirect any "erroneous" redirects in the last few days/weeks will have also been cached by the browser.
    – MrWhite
    Jan 23 at 10:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.