Wildcard for SetEnvIfNoCase Remote_Host in htaccess - regex

I want to restrict access to a directory using SetEnvIfNoCase and a wildcard for Remote_Host. For example, I'd like to permit access to the directory for any client requesting the directory from *.example.com.
(In practice, I'm going to use it to restrict access of this directory to requests from googlebot.com, etc.)
What I have in my htaccess does not work and I believe it is because of an improperly formatted wildcard:
SetEnvIfNoCase Remote_Host ^(.*).example.com$ OK_friend
Order Deny,Allow
Deny from All
Allow from env=OK_friend
I have tried changing the Remote_Host to Remote_Addr and putting my IP address, and everything works fine. I just can't seem to get this to work for a wildcard on the remote hostname.

Try non-greedy by adding a "?" and escape your "." since it is a RegEx metacharacter:
^(.*?)\.example\.com$
Or you can simplify it further if you're just running a check without capturing any groups:
^.*?\.example\.com$

Related

Apache DirectoryMatch apply in one subfolder but not in another

i'm trying to apply some rules for a subfolder but not for another subfolder.
I have this
SetEnvIf Referer "((.+\.)?domain\.com|localhost)" localreferer
<DirectoryMatch "/bin(.+/)?">
Require env localreferer
</DirectoryMatch>
And it is working fine. But now I need that this rule does not apply to /bin/public. I will have /bin/private and /bin/public, i need to apply the rule for /bin/private
I tried with
SetEnvIf Referer "((.+\.)?domain\.com|localhost)" localreferer
<DirectoryMatch "/bin/private(.+/)?">
Require env localreferer
</DirectoryMatch>
But all bin's subfolders are allowed from all referer.
What would be the correct regular expression to allow /bin/public to be accessed from any referer and /bin/private only from the ones I have on the list
Thanks in advance
i found the issue and the solution. i need to use LocationMatch instead of DirectoryMatch, so
SetEnvIf Referer "((.+\.)?domain\.com|localhost)" localreferer
<LocationMatch "/bin(.+/)?">
Require env localreferer
</LocationMatch>
<LocationMatch "/bin/public(.+/)?">
Require all granted
</LocationMatch>

Django Invalid HTTP_HOST header on Apache - fix using Require?

A couple weeks ago, I had a wonderful time setting up an Apache and Django configuration to work while forcing SSL and operating behind an AWS load balancer.
Now that it is all working nicely, I'm still constantly receiving the common "Invalid HTTP_HOST header" error, and trying to figure out the right way to go about fixing it.
Searching has brought me to the following answer regarding the Apache configuration:
How to disable Django's invalid HTTP_HOST error?
Which recommends placing the following settings inside the <Directory></Directory> block in the VirtualHost file:
SetEnvIfNoCase Host .+ VALID_HOST
Order Deny,Allow
Deny from All
Allow from env=VALID_HOST}
This works, but according to Apache (https://httpd.apache.org/docs/2.4/howto/access.html) this method is deprecated.
I've read through the Apache docs but when I tried using the following code it just shut down access to the site and gave me a "Not Authorized" error.
<RequireAll>
Require host example.org
</RequireAll>
Not entirely sure what I'm missing. I know I can solve the problem using the first answer, just trying to figure out the "right" way using code that isn't deprecated. Site is using WSGIDaemonProcess to run the Django App and has the following set to force the SSL through AWS
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTP:X-Forwarded-For} !=""
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}
No need to use mod_setenvif as HTTP_HOST is already a variable and you can evaluate it directly.
<Directory /var/www/html/>
Require expr %{HTTP_HOST} == "example.com"
Options
</Directory>
So, after messing with this for a long time I figured out that the problem I was dealing with may have something to do with the hostname reverse DNS lookup failing, since the IP address was pointing to an AWS EC2 instance instead of my domain.
After finally giving up on getting it right I returned to the post on how to disable the log error, and tried using the env variable, which seems to be working.
Apparently the correct format for Require is:
<Directory /var/www/html/>
SetEnvIfNoCase Host example\.com VALID_HOST
Require env VALID_HOST
Options
</Directory>
These guys had it right, just need to update it for the current "Require" directive.
How to disable Django's invalid HTTP_HOST error?

Apache mod_alias RedirectMatch everything except specific pattern

Good old regular expressions are driving me nuts.
I need to redirect all traffic in Apache 2.4 from HTTP to HTTPS, except for "/bt/sub/[a_few_endings]", using Redirect from mod_alias (can't use mod_rewrite).
I tested the following regular expression in all online testers I know (e.g. http://regex101.com/) and all confirm that the regex should indeed match everything except the URLs I don't want it to match:
^/(?!bt/sub/(went_active|success|cancel|expired)).*$
As far as I can tell, this should match everything in http://local.mysite.com and redirect it to https://local.mysite.com, except for the following four:
http://local.mysite.com/bt/sub/went_active
http://local.mysite.com/bt/sub/success
http://local.mysite.com/bt/sub/cancel
http://local.mysite.com/bt/sub/expired
Still, Apache redirects everything, including the above URLs I don't want redirected.
I found several similar questions in SO but most of them are answered in the light of mod_rewrite, which is not what I want/need, and the ones that people say have worked have not worked for me.
Here's my virtual host configuration as it currently stands:
<VirtualHost *:80>
ServerName local.mysite.com
RedirectMatch 302 ^/(?!bt/sub/(went_active|success|cancel|expired)).*$ https://local.mysite.com
DocumentRoot /home/borfast/projects/www/mysite/public
#Header set Access-Control-Allow-Origin *
SetEnv LARAVEL_ENV localdev
<Directory /home/borfast/projects/www/mysite/public/>
Options All
DirectoryIndex index.php
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Please help and prevent me from going crazy :)
UPDATE:
There's something weird going on: apparently when the requested URL/path can be found, Apache ignores the expression in RedirectMatch and redirects the client, even though the RedirectMatch tells it not to.
To test this I created a new virtualhost from scratch inside a separate VM freshly installed with Ubuntu Trussty 64, loaded with Apache 2.4. This new virtual host contained just the ServerName, RedirectMatch and DocumentRoot directives, like this:
<VirtualHost *:80>
ServerName testing.com
RedirectMatch 302 ^/(?!bt/sub/(went_active|success)$).*$ https://othersite.com/
DocumentRoot /home/vagrant/www
</VirtualHost>
I created the directory /home/vagrant/www/bt/sub/went_active to make sure Apache could get to at least one of the two possible URLs. When trying to access http://testing.com:8080, I get redirected, as expected.
Then the weirdness comes: when accessing http://testing.com:8080/bt/sub/went_active, the URL that matches the directory I created, I am still redirected, even though I shouldn't be, but when accessing http://testing.com:8080/bt/sub/success, I don't get redirected and instead get a 403 Forbidden.
I may be losing my sanity over this but it seems that when Apache sees that it could serve the request and it matches the regular expression in RedirectMatch that should prevent the redirect, it decides to ignore the regular expression and do the redirect anyway. Three letters for this: WTF?!?!?!
As it was said in comments - it is easier to do with mod_rewrite. Possible solutions
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/bar/(abcd|baz|barista|yo)$ [NC]
RewriteRule ^ http://site/ [R=301,L]
Another one (for .htaccess, as initial / is removed from RewriteRule)
RewriteEngine On
RewriteRule !^bar/(abcd|baz|barista|yo)$ http://site/ [R=301,L,NC]
And solution by RedirectMatch
RedirectMatch permanent ^(?!/bar/(abcd|baz|barista|yo)$).* http://site/
All work perfectly, the problem that you might have on a testing/debugging state is that browser caches 301 response. So, when you are trying to check or to write the correct code - use 302 response, not 301. And remove NC flag if case insensitivity is not required.
See this one
^\/.*(?<!foo\/bar\/(aaa|bbb|ccc|ddd))$
Match / followed by anything, unless the end of string is preceded by /foo/bar/(aaaa|bbb...)
The (?<! is a negative lookbehind attached to end of string $ which will check its impossible to match what's inside just before the end of string.
If your real case is not as static as your exemple, give real datas for the query part.

using regex for proxypass

I'm trying to set up a proxy to my corporate environment's ActiveMQ admin pages on our standard http proxy server. I have a rule in place that allows me access to the admin landing page:
ProxyPass /foobar hostname:8161/admin
ProxyPassReverse /foobar hostname:8161/admin
However, going to the "queues" page bring me to a different page appended with a unique session ID (admin/queues.jsp;jsessionid=oq37zgvxz4zkwliwdwddyon3), and I would like for this page to be accessible through the same URL as well.
Attempting to add a wildcard (*) at the end of these proxypass rules breaks the redirect. Is there a redirect rule that I need to use in conjunction with this, and how do I get any string to this host to pass through this proxy rule?
There is ProxyPassMatch that is regex based, but ProxyPass does prefix matching (i.e. a ProxyPass for /foo should catch /foo/bar too) so your current rule should work anyway.
It may be that the redirection URL doesn't match the reverse rule for some reason. I have to admit I've never managed to get a ProxyPass to Tomcat to work correctly when the front and back end context paths differ, so my advice would be to deploy the back end app at hostname:8161/foobar instead of /admin if that's an option.

Use .htaccess to restrict external access to my Intranet

I'm sure this is possible, but its beyond my meager abilities with .htaccess files.
We have an internal php app that we use, we have basic security internally, but dont need to worry too much. I would like to make it available online for use when staff are out and about. I would like to have additional security based on htaccess or htpassword files.
Is it possible to write a htaccess file that does the following
If user is accessing from office.mydomain.com it means they are internal (office.mydomain.com resolves to an internal ip like 192.168.22.22) so allow unimpeded access
If the user is accessing from outside it will be external.myoffice.com - if this is the case as an added bit of security I would like to use .htaccess and a password file to get the user to enter an apache password.
Can anyone tell me how to write this with .htaccess file?
Update: Thanks for all the answers, I have posted what worked for me as an answer to help others.
You can use
RewriteCond %{REMOTE_ADDR} !^192\.168\.
to specify the condition of an external IP, or use
RewriteCond %{REMOTE_ADDR} ^192\.168\.
for the condition of a local IP.
You will just have to integrate these into your existing htaccess rules in a sensible way.
I think this does do what you want;
http://codesanity.net/2009/11/conditional-htpasswd-multienvironment-setups/
http://tomschlick.com/2009/11/08/conditional-htpasswd-multi-environments/
https://tomschlick.com/2009/11/08/conditional-htpasswd-multi-environments
Correct address for the resource as of 2022/01/15.
https://tomschlick.com/conditional-htpasswd-multi-environments/
Here you go
order deny,allow
allow from 192.168.22.0/255.255.255.0
deny from all
You can use a subnet mask to make sure the visitors are from the same network. If you need to address another network, just use those IP's (as the server sees them)
To Complete this answer the following Works.
#allows everything if its on a certain host
SetEnvIf HOST "^www.mysite.com" external_url
SetEnvIf HOST "^localhost" local_url
Order Deny,Allow
AuthName "Restricted Area"
AuthType Basic
AuthUserFile path/to/your/.htpasswd
AuthGroupFile /
Require valid-user
#Allow valid-user
Deny from all
Allow from env=external_url
Allow from env=local_url
Satisfy any
This pops up a Restricted Area login box if you visit via the www.mysite.com but displays nothing if you are coming locally.