I want to restrict access to a website to only allow referrers from a single domain. I can't get the .htaccess file to work correctly.
Say I am referring from http://domainname.com - access will be allowed.
Or http://subdomain.domainname.com - access will be allowed.
But any other referrer (or typing in URL) will block, and direct to Access Denied page.
Code as follows (note I need to allow access from ANY referrer page on domainname.com
RewriteEngine On
RewriteBase /
# allow these referers to passthrough
RewriteCond %{HTTP_REFERER} ^http://(protect|unprotected)\.domainname\.com
RewriteRule ^ - [L]
# everybody else receives a forbidden
RewriteRule ^ - [F]
ErrorDocument 403 /forbidden.html
The HTTP referer header only says were the request is coming from. E.g. when there is a link in some webpage from www.example.net
<a href="http://www.example.com/some/path>Click here</a>
then the request will be for http://www.example.com/some/path and the referer header will contain the URI from www.example.net.
If you block any request without a specific referer, then any direct request will be blocked too. Also note, that the referer header is sent by the client and therefore, it is not a reliable indicator.
Another caveat is, according to Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content- 5.5.2 Referer, the client may send a partial-URI, which doesn't contain a domain name at all.
To answer your question, if you want to allow requests coming from either domainname.com or any of its subdomain, you might check for
RewriteCond %{HTTP_REFERER} ^http://(?:.*\.)?domainname\.com
RewriteRule ^ - [L]
RewriteRule ^ - [F]
or the other way round, forbid when you negate it
RewriteCond %{HTTP_REFERER} !^http://(?:.*\.)?domainname\.com
RewriteRule ^ - [F]
To check for one of multiple conditions, cond1 or cond2 or cond3, you must use RewriteCond with the ornext|OR flag, e.g.
RewriteCond %{HTTP_REFERER} ^http://(?:.*\.)?nature\.com [OR]
RewriteCond %{HTTP_REFERER} ^http://(?:.*\.)?adclick\.g\.doubleclick\.net [OR]
RewriteCond %{HTTP_REFERER} ^http://(?:.*\.)?onepointedpixel\.com
RewriteRule ^ - [L]
Related
Im helping a friend out on a website which is created using an online platform powered by plesk and theres an issue when trying to access this web through google.
Writing the domain directly in the browser works fine but when accessing it through a google search it redirects the user back to google.
What could be the issue?
this is my .htaccess file
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
#HTTP-HTTPS
RewriteCond %{HTTPS} off
RewriteRule (.*) https://srad.wtf/es_ES/$1 [R=301,L,QSA]
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite all other queries to the front controller.
RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 307 ^/$ /index.php/
# RedirectTemp cannot be used instead
</IfModule>
</IfModule>
Ive removed the majority of the comments from the file to keep it clean
As stated in comments, there doesn't appear to be anything in your .htaccess file that would cause this redirect.
the redirect response ... appears to be coming from an Nginx server (possibly a front-end proxy), not Apache.
#MrWhite does that mean its something that I cant solve myself?
The Nginx server, from which the response is ultimately being served from/through (a front-end/caching proxy I suspect) is part of your server config - so you would expect to have some control over this - although "using an online platform" then maybe not?
However, the redirect(s) you are seeing may be coming from your application server/PHP (not Nginx or Apache). The problem isn't just with "Google Chrome" (as you have tagged) or even with Google SERPs. Any inbound link to the homepage is being 302 redirected back to itself (the HTTP Referer).
Not wanting to sound alarming, but this sort of redirect is quite typical of a site being hacked - as it is potentially damaging for SEO. Although since this only affects the homepage and is a 302 (temporary) redirect and you appear to have other language specific redirects in the application logic then this may just be a missconfiguration - although redirecting back to the "HTTP Referer" is quite a deliberate action!
For example, the following link to your homepage currently 302 redirects back to "this page"!
https://srad.wtf/
Workaround
Your site appears to be in two languages, as denoted by the first path segment, /en/ or /es_ES/ (default). The application logic appears to unconditionally redirect(302) to /es_ES/ if omitted (it is not deduced from the user's browser preferences or remembered for returning visitors).
You may be able to redirect to /es_ES/ early in .htaccess before the application kicks in. (By the same logic that requesting the HTTP homepage also works OK, since it is redirected to HTTPS early in .htaccess.)
Try the following, after the RewriteEngine directive:
RewriteRule ^$ https://example.com/es_ES/ [R=302,L]
Note that this is a "workaround", it doesn't fix the underlying problem.
Additionally...
#HTTP-HTTPS
RewriteCond %{HTTPS} off
RewriteRule (.*) https://srad.wtf/es_ES/$1 [R=301,L,QSA]
This HTTP to HTTPS redirect is not strictly correct, as it unconditionally prefixes the request with /es_ES/ even when a valid language code might already be present. eg. Request http://example.com/es_ES/about (HTTP) and you are redirected to https://example.com/es_ES/es_ES/about (404). etc.
The HTTP to HTTPS redirect should simply redirect to the same URL-path (resolve any other language/path issues elsewhere*1). For example, this should be written:
RewriteCond %{HTTPS} off
RewriteRule (.*) https://example.com/$1 [R=301,L]
The QSA (Query String Append) flag is not required since the query string (if any) is passed through by default, unless you create a new query string on the substitution string (the QSA flag would then be required to append the query string from the original request).
(*1 To some extent, the preceding "workaround" resolves the missing language code.)
Strictly speaking, the language should be defaulted conditionally based on the value of the Accept-Language HTTP request header - but this is best done in PHP, not .htaccess.
We have tried adding the below hotlink protection inorder to save the bandwidth.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain [NC]
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain.*$ [NC]
RewriteRule \.(gif|GIF|jpg|JPG|PNG|png|jpeg|JPEG|mp4|MP4|mkv|MKV|webm|WEBM|ico|ICO)$ - [F]
This is working perfectly. Now, we want to exclude hotlink protection for the URL admin/thumbs (domain.tld/admin/thumbs/image.jpg) should be excluded from the hotlink protection.
We tried adding the below code however its not working. We searched on stackoverflow and multiple forums however none were helped us.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain [NC]
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain.*$ [NC]
RewriteCond %{REQUEST_URI} !/admin/thumbs$
RewriteRule \.(gif|GIF|jpg|JPG|PNG|png|jpeg|JPEG|mp4|MP4|mkv|MKV|webm|WEBM|ico|ICO)$ - [F]
Any help would be appreciated.
RewriteCond %{REQUEST_URI} !/admin/thumbs$
This creates an exception for any URL that ends with /admin/thumbs, whereas it would seem you want to create an exception for any file in the /admin/thumbs subirectory, ie. any URL that starts /admin/thumbs.
The suggestion !^admin/thumbs/? in comments is incorrect, since the REQUEST_URI server variable always starts with a slash so the condition will always be successful and the request is potentially blocked.
You should use the CondPattern !^/admin/thumbs($|/) instead to exclude requests for /admin/thumbs, /admin/thumbs/ and /admin/thumbs/<anything>, but not /admin/thumbsomething. For example:
RewriteCond %{REQUEST_URI} !^/admin/thumbs($|/)
Your existing rule can be further simplified/refined since the existing conditions that check the HTTP_REFERER are "the same", but also match too much. And the mixed case RewriteRule pattern can be flattened by using the NC (nocase) flag instead.
For example, the complete rule would become:
# Hotlink protection for images, except those in "/admin/thumbs/..."
RewriteCond %{HTTP_REFERER} !^https://(www\.)?example\.com($|/) [NC]
RewriteCond %{REQUEST_URI} !^/admin/thumbs($|/)
RewriteRule \.(gif|jpg|png|jpeg|mp4|mkv|webm|ico)$ - [NC,F]
Note that this also blocks an empty Referer header. This includes direct requests (anyone typing the URL directly into the browser's address bar) and any user that has suppressed the Referer in their browser (which some users do for increased privacy).
Alternative solution with additional .htaccess file
Alternatively, you could create an additional .htaccess in the /admin/thumbs/ subdirectory and simply disable the rewrite engine. For example:
RewriteEngine Off
This overrides and prevents the hotlink-protection directives in the parent config from being processed when anything within this subdirectory is requested.
I have a folder on my site (domain.com/protect) I want to limit to only one referrer (otherdomain.com/subfolder).
Deny for all others, allow only if coming from that URL.
If not coming from that URL, then redirect the visitor over to otherdomain.com/login instead.
How would I write that out in .htaccess rewrite rules?
In the htaccess file in your /protect directory, add these rules:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !otherdomain\.com/subfolder
RewriteRule ^ - [L,F]
The condition checks that the referer doesn't contain: otherdomain.com/subfolder, and if it doesn't, then whatever the request is (inside the /protect directory) will result in a 403 Forbidden.
Alternatively, you can put these rules in the htaccess file in your document root if you would rather keep everything in once place:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !otherdomain\.com/subfolder
RewriteRule ^/?protect/? - [L,F]
I'm trying to set up a htaccess file that would accomplish the following:
Only allow my website to be viewed if the viewing user is coming from a specific domain (link)
So, for instance. I have a domain called. protect.mydomain.com . I only want people coming from a link on unprotected.mydomain.com to be able to access protect.mydomain.com.
The big outstanding issue I have is that if you get to protect.mydomain.com from unprotected.mydomain.com and click on a link in the protect.mydomain.com that goes to another page under protect.mydomain.com then I get sent back to my redirect because the http_referer is protect.mydomain.com . So to combat that I put in a check to allow the referrer to be protect.mydomain.com as well. It's not working and access is allowed from everywhere. Here is my htaccess file. (All this is under https)
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_REFERER} ^https://(.+\.)*mydomain\.com
RewriteCond %1 !^(protect|unprotected)\.$
RewriteRule ^.*$ https://unprotected.mydomain.com/ [R=301,L]
You are matching your referer against ^https://(.+\.)*mydomain\.com. Which means if some completely other site, say http://stealing_your_images.com/ links to something on protect.mydomain.com, the first condition will fail, thus the request is never redirected to https://unprotected.mydomain.com/. You want to approach it from the other direction, only allow certain referers to pass through, then redirect everything else:
RewriteEngine On
RewriteBase /
# allow these referers to passthrough
RewriteCond %{HTTP_REFERER} ^https://(protect|unprotected)\.mydomain\.com
RewriteRule ^ - [L]
# redirect everything else
RewriteRule ^ https://unprotected.mydomain.com/ [R,L]
I've got different users for my website, owning different images which are all stored in the same folder. The images are stored in an incremental fashion, 1.jpg, 2.jpg etc.
User can view these pictures on a specific php page. Now I want to restrict the access to these images only through this php page so that they can't simply enumerate all the filenames to see the images of other users.
I thought of doing this with an .htaccess file which is stored besides the images in /shop/img/userimg/ and would look something like this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/shop/shop.php [NC]
RewriteRule .*\.(jpe?g|gif|bmp|png)$ - [F]
My site is a subsite (as you can see: /shop/) and the php page to view these images would be shop.php.
Now, is this possible at all? What am I doing wrong?
Note that the referer header is not to be trusted. Some proxies and firewall remove the header entirely, so you have to account for it not being present (that's what the 2nd line is for)
RewriteCond %{HTTP_REFERER} !/shop/shop\.php$ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule \.(jpe?g|gif|bmp|png)$ - [F,L]
Try adding the following to your htaccess file.
RewriteEngine On
RewriteBase /
#if the referer (page request came from) does not contain shop.php
RewriteCond %{HTTP_REFERER} !/shop/shop\.php [NC]
#and it is a request for images, then send a 403 forbidden
RewriteRule \.(jpe?g|gif|bmp|png)$ - [F,L]