Apache cookie-based transparent proxy / redirect - apache

I have a number of sites running on the same machine, served by httpd. Each of the sites is set up as a VirtualHost on a different subdomain. Furthermore, for each subdomain, there are two VirtualHosts on different ports: one for the 'stable' version, one for the 'beta' version. The stable version is hosted on port 80.
Upon logging into the (stable version of the) sites, a cookie is set if the backend determines the user should be using the beta version.
I'd like Apache to detect this cookie on subsequent requests to the stable version and (without the user being aware) redirect the request to the beta version.
How can I achieve this?
I've tried using RewriteCond / RewriteRule in httpd.conf, but it doesn't seem to have any effect - perhaps Apache ignoring it in favour of the matching VirtualHost, or is sensitive to ordering (I think the VirthalHost definitions are being included first)? Perhaps I should be using mod_proxy, anyway?
Config
I've included (anonymised) snippets of my config below
httpd.conf
Listen 80
NameVirtualHost *:80
Listen 81
NameVirtualHost *:81
Include "/path/to/checkout/config/[stage]/apache2/*.conf" # VirtualHosts of sites
Include "/path/to/checkout/config/common/apache2/*.conf" # My attempted redirect
config/[stage]/apache2/[site]/apache2/[app-stable].conf
<VirtualHost *:80>
ServerName [app.hostname]
ServerAlias [alternative-app-name.hostname]
DocumentRoot "/var/www-application/release-base/current/app/public"
<Directory "/var/www-application/release-base/current/app/public/">
Options Indexes FollowSymLinks
AllowOverride All
</Directory>
<!-- snip -->
</VirtualHost>
config/[stage]/apache2/[site]/apache2/[app-beta].conf
<VirtualHost *:81>
ServerName [app.hostname]
ServerAlias [alternative-app-name.hostname]
DocumentRoot "/var/www-application/beta-release-base/current/app/public"
<Directory "/var/www-application/beta-release-base/current/app/public/">
Options Indexes FollowSymLinks
AllowOverride All
</Directory>
<!-- snip -->
</VirtualHost>
config/common/apache2/common.conf
# !!! This has no effect !!!
RewriteEngine On
RewriteCond %{HTTP_COOKIE} cookiename
RewriteCond %{SERVER_PORT} !8081
RewriteRule ^ https://%{HTTP_HOST}:8081%{REQUEST_URI} [R,L] # (R for debugging)
App .htaccess (in case it's relevant)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

You have two problems:
The redirects in global scope are ignored; move them to vhost scope
The "%{HTTP_HOST}" var includes the port number, so you are redirecting to http://hostname:80:81/foo (hence your "hang")
In order to make this transparent, you need to use the [P] flag on the RewriteRule, and include a ProxyPassReverse directive. Your final directives (in each 'stable' conf file) should be as follows:
RewriteCond %{HTTP_COOKIE} absVersion
RewriteRule ^/(.*) http://hostname:81/$1 [P]
ProxyPassReverse / http://hostname:81/
Note that this requires mod_proxy (and any necessary submodules, e.g. mod_proxy_http) to be enabled.

Related

Apache: Using VirtualHost redirect to URL with RewriteCond applied?

So I have a RewriteCond that turns:
domain.com/view.php?a=1
into:
domain.com/artist/name
I have a shorter domain: dmn.com that I would like to provide shortlinks for artists:
dmn.com/name
How can I get dmn.com/name to redirect to: domain.com/artist/name while keeping the shortlink in tact?
.htaccess:
#rewrite profile requests
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule artist/(.*)$ view.php?a=$1 [QSA,NC,L]
httpd.conf:
<VirtualHost *:80>
DocumentRoot /var/www/html/ // <-- ??? not sure what to put here
ServerName dmn.com
ServerAlias www.dmn.com
</VirtualHost>
Since the directory "/artist" doesn't actually exist (since it's being rewritten), I can't seem to put /var/www/html/artist in the DocumentRoot of the VirtualHost config without Apache spitting back:
Warning: DocumentRoot [/var/www/html/artist] does not exist
I think what you want is not an actual redirection, but another rewrite.
You can't do it with a separate VirtualHost. Well, you can if you point it to the same DocumentRoot and duplicate your rules or load them from a common file, either via .htaccess or a Include directive.
You can also add the short domain name to your main domain ServerAlias
<VirtualHost *:80>
# This should point to your current config
DocumentRoot /var/www/artists_profiles/
ServerName example.com
ServerAlias www.example.com ex.com www.ex.com
</VirtualHost>
Then you add the new rules to the top of the file:
RewriteBase /
RewriteCond %{HTTP_HOST} ex.com
RewriteRule ^(^.*) artist/$1
Then your existing rules should pick up. If you want to avoid the shortened domain from responding to the longer urls you could add a similar RewriteCond to the existing rules:
RewriteCond %{HTTP_HOST} !ex.com

Apache port being automatically forwarded

I'm trying to have two different directory associated to two different ports. (8001 and 8004), but whenever I try to access port 8004 in a browser, it redirects automatically to port 8001.
Here's some extract of the config files that seems relevant:
In httpd.conf:
Listen 80
Listen 8001
Listen 8004
Removed comment to line:
Include etc/apache24/extra/httpd-vhosts.conf
In file httpd-vhosts.conf:
<VirtualHost *:8001>
DocumentRoot "<path_to_site_1>"
<Directory "<path_to_site_1>">
Require all granted
</Directory>
<Directory "<path_to_site_1>">
AllowOverride All
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]
</Directory>
</VirtualHost>
<VirtualHost *:8004>
DocumentRoot "path_to_site_2"
<Directory "path_to_site_2">
Require all granted
</Directory>
<Directory "path_to_site_2">
AllowOverride All
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]
</Directory>
</VirtualHost>
Here's a list of things I've tried, that didn't change anything:
Having the VirtualHost declaration in httpd.conf
Changing the order of the Virtual host declaration
Changing port 8004 to another port
Clear the browser cache and try a different browser
If I comment Listen 8001, it breaks everything.
Port 80 seems to point to the default www directory of this FreeBSD installation and still works properly, for phpMyAdmin is installed there and is still accessible.
Maybe of note, it's a FreeBSD installation running on Oracle VM VirtualBox.
Thank you for any help or ideas to follow.
Unfortunately, in this case, the comportment wasn't due to Apache configuration but to the website installations. One was a WordPress installation and the other was a Drupal installation. I wasn't aware that by moving those website in the directory structure, they would no longer point at the right place. WordPress was doing the redirection.
The issue was solved with two different solution, one for each platform.
For WordPress:
In the file functions.php, located in the theme directory:
Add the following lines:
update_option( 'siteurl', '<new_url>' );
update_option( 'home', '<new_url>' );
In the browser, fefresh the website a few time
Remove both lines from the file
For Drupal:
(using drush) In the directory where the website is located:
drush cache-rebuild
The combination of both commands solved the issue with both installation.

Apache httpd.conf - Link multiple domains to corresponding subfolders

I need a rule to internally rewrite several domains, with and without www:
www.a.com --> /m/n/o/
b.c.org --> /x/y/z/
The setup is Apache running locally on Windows (XAMPP). I've got the hosts file set up so all the domains point to localhost. I'd like every page to get redirected, i.e. I want to point each domain to it's own different root directory and have it work normally from there. e.g.
/ <-- Top level folder, everything is under here.
/root/of/domain/A/ <-- www.a.com
/root/of/domain/C/ <-- b.c.org
You have two choices.
(1) The one you asked (with mod_rewrite)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)?a\.com$ [NC]
RewriteRule ^/(.*)$ /root/of/domain/A/$1 [L]
RewriteCond %{HTTP_HOST} ^b\.c\.org$ [NC]
RewriteRule ^/(.*)$ /root/of/domain/C/$1 [L]
</IfModule>
Note: don't forget to replace example values by real ones. Also, make sure mod_rewrite is enabled.
(2) the cleanest way: configure virtualhosts directly (without mod_rewrite)
NameVirtualHost *:80
<VirtualHost *:80>
DocumentRoot "X:/path/to/root/of/domain/A/"
ServerName a.com
ServerAlias www.a.com
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "X:/path/to/root/of/domain/C/"
ServerName b.c.org
</VirtualHost>

Apache configuration / Catch-all subdomain / Specific subdomain exception

Startting with some simple domain setup :
<VirtualHost *:80>
ServerName site.com
ServerAlias *.site.com
DocumentRoot /path/to/site.com
<Directory /path/to/site.com>
AllowOverride all
Options -MultiViews
</Directory>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$ [NC]
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{HTTP_HOST} ^(.*).site.com$ [NC]
RewriteRule ^(.*)$ http://site.com$1 [R=301]
RailsEnv production
</VirtualHost>
So I'm pretty happy, anything put before my domain will be removed and my urls will always be clean : http://site.com
Cool!
** BUT **
I'd like to set a specific subdomain (an exception in that case) which would point to another site on the same server (another folder, another slightly different apache config, etc…)
This setup above will always precedes the one I would do for my 'exception' dubdomain.
How could I reach the goal described ? Catch-all apache setup with one (or some more) subdomain setup exceptions ?
Try to add you configuration for desired subdomain above this code, it should help.

Apache URL Rewriting misbehaving

I have the setup below; a very simple URL rewrite setup with a test setup
// ----- test.php -----
<?php
phpinfo();
// ----- test.php -----
The config for test.local is as below.
<VirtualHost *:80>
ServerName test
ServerAlias test.*
DocumentRoot /var/www/test
</VirtualHost>
<Directory "/var/www/test/">
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* test.php/$0 [R,NE]
</Directory>
Now if I make a request GET http://test.local/my-path-info the default phpinfo() page appears as expected, if I add slash in the path info, that works too. But if I add an encoded forward slash %2F into the URL (example GET http://test.local/my-path-info%2fsomething-else), it comes up as 404 Not found. Basically it doesn't get to the php file.
Any idea why this is happening, and how to get around it?
The setup is on Apache 2.2.13, PHP 5.3.8 on Linux (Centos 5.x).
NOTE: What I am trying to do here is to add a forward slash into one of the path-info components, such that it doesn't get interpreted by the router logic in an MVC framework. Without encoding it, the router cannot differentiate between a slash that is a path separator and the one that is part of a path component.
Because of the apache version that doesnt support NoDecode as an option for AllowEncodedSlashes, I ended up using the below combination. I also had to double url-encode the request URI. Not ideal but works for me for the moment.
<VirtualHost *:80>
ServerName test
ServerAlias test.*
DocumentRoot /var/www/test
AllowEncodedSlashes On
</VirtualHost>
<Directory "/var/www/test/">
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Option B below was the key!
RewriteRule .* test.php/$0 [R,NE,B]
</Directory>