Django Invalid HTTP_HOST header on Apache - fix using Require? - django

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?

Related

Apache conditional Header per Referer

I have this configuration on NgINX Server and I need to have the same rule on another Web Server that runs Apache.
NgINX
if ($http_referer !~ "^https?:\/\/.*\.sitea\.com.*|https?:\/\/.*?\.siteb\.com.*|https?:\/\/sub\.sitea\.com.*|?$") {
add_header X-Frame-Options "DENY";
}
I try to use the following code, but I receive an Internal Server Error
Apache
<IfModule mod_headers.c>
<If "%{HTTP_REFERER} !~ m#^https?:\/\/.*\.sitea\.com.*$#">
Header append X-Frame-Options "DENY"
</If>
</IfModule>
Could you anybody help to find the right way to do that?
I find this solution that works fine with old Apache versions.
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^https?:\/\/.*\.sitea\.com.*?$ [NC]
RewriteRule ^ - [E=NOFRAME:1]
Header append X-Frame-Options "DENY" env=NOFRAME
In this way I'm able to put X-Frame-Options conditionally according to a list of authorized domains.
This is a failback for old browsers that don't use Content Security Policy rules.
You can see here the full list.
Header append Content-Security-Policy "frame-ancestors sitea.com"
So modern browsers will use the CSP2 rule, older use the X-Frame-Options. Thanks to regex we could apply this option to a list of allowed domains.
Expressions came with Apache 2.4. Yours is definitely older than that.

Rewrite virtual servers directory into a top level domain

I would like to rewrite directories of my RootDocument into thei'r own addresses.
For exaimple, I would like to be able to visit: http://localhost/FOO and be redirected to http://FOO.dev. Please note that the URL domain is static ass all subdirectory domains will have the same tol-level domain. I need to create a redirect within chunk of code:
<VirtualHost *:80>
ServerName 127.0.0.1
ServerAlias localhost
DocumentRoot /usr/local/var/www
<Location />
Options All
AllowOverride All
Require all granted
</Location>
<LocationMatch ^/[^.].+/$>
RewriteEngine on
/*
I NEED A REWRITE HERE WHEN I REACH THE DIRECTORY LOCATION
AS LOCATION IS ALREADY MATCHED, I'M NOT SURE HOW TO EXTRACT IT
*/
</LocationMatch>
<LocationMatch ^/[.].+/$>
Options none
AllowOverride none
Require all denied
</LocationMatch>
</VirtualHost>
Since I have already figured out how to get into directories I need to be at, how would I use my logic to extract and redirect me into correct place?
You need a two-step-approach for this, since you have to handle two separate requests in the scenario you want to set up:
This is the rule to redirect clients to the new host name:
RewriteEngine on
RewriteRule ^/?(\w+)(/?.*)$ http://$1.dev$2 [R=301]
This is the rule inside that host to remap the request onto the internal folder in the file system again:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(\w+)\.dev$
RewriteCond /%1 -d
RewriteRule ^/?(.*)$ /%1/$1 [END]
Obviously the rewriting needs to be loaded and enabled for this.
In case you receive back a http status 500 ("internal server error") for the first request (the one to be redirected) chances are that you are using a very old version of the apache http server. In that case try replacing the [END] flag with the [L] flag...
Above rules will work likewise in the http servers host configuration or in dynamic configuration files. However you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

Insert a directory at the start of a URL in Apache Config

Apologies if this question has already been asked before. I couldn't find an example that handled my exact situation.
I have an Apache Server and have access to the httpd.conf file.
I have a domain (say www.example.com) and I want to insert a directory (say test) after the domain.
So for example I want www.example.com to be mapped to www.example.com/test and www.example.com/folder to be mapped to www.example.com/test/folder and so on.
I have achieved this using the a RedirectMatch directive like this:-
<VirtualHost *:80>
ServerName www.example.com
RedirectMatch ^/$ test/
</VirtualHost>
However this changes the URL in the browser to include the test folder and I would like to keep this hidden from the end user.
I have tried using a rewrite rule but my lack of regex knowledge has let me down here! This is what I have tried (within the virtual host element):-
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/test/
RewriteRule ^(.*)$ /test/$1
I have tried various combinations with this but nothing seems to work!
Any help would be much appreciated.
Ok, I found the problem here. This was working ok but my browser cache (Firefox) was remembering the old values.
I turned of caching in the browser (by going to about:config and setting browser.cache.disk.enable = FALSE
Then everything started working correctly.
Hopefully this will help others who have the same issue!

Hosting a wordpress blog parallel with a django app

I would like to host a blog at a subfolder of my domain, which is covered by a django app. I'm most of the way there, but I need some help getting over the finish line, as it were.
Currently, if I go to domain.com, the django app is served correctly. If I go to domain.com/blog/, the blog is served correctly. However, if I go to domain.com/blog (note the missing trailing slash), the urlconf returns a URL not found error.
I've tried a couple of things, including:
Reordering the Alias, Directory, and WSGIScriptAlias statements in my Apache configuration
Having the django urlconf trap the domain.com/blog condition and redirect to domain.com/blog/ (probably unsurprisingly causing an infinite loop of redirects)
What are my next steps?
Here is the relevant part of my Apache conf:
Alias /blog/ /var/www/blog/
<Directory /var/www/blog/>
AllowOverride All
Order deny,allow
Allow from all
</Directory>
I haven't used Apache in years, but try aliasing just /blog instead of /blog/. The problem currently is that Apache is not catching it, so it's being passed to Django. If that doesn't work, you might also try setting up a 301 redirect in your Apache conf to redirect to the slash version, thereby avoiding Django altogether.

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.