Is it possible to use "%{HTTP_HOST}" in ProxyPass? - apache

I'm trying to implement a transparent proxy using apache2 and mod_proxy that for now - doesn't do anything. just forwards the traffic to the correct "host".
I don't want it to be host-dependant - but dynamic so it'll work for all hosts.
I tried to do this:
RewriteEngine on
RewriteLogLevel 5
RewriteLog "/var/log/apache2/rewrite.log"
RewriteRule ^(.*)$ $1
ProxyPass / http://$1
I also tried several other approaches (none worked).
Is there any way I can access the "host" from the header and use it in the ProxyPass directive?
In nginx I would use $host, $remote_addr, etc.. any way to replace that on apache?
What I need is to be able to access %{HTTP_HOST}, %{REQUEST_URI} and %{SERVER_PORT} inside the ProxyPass command.

To use Apache ProxyPass directives with dynamic hostnames you will need to also use ModRewrite.
Objective
All requests to the virtualhost will ProxyPass and ProxyPassReverse (also known as an "Apache Gateway") to the %{HTTP_HOST}
The only reason this would make sense to do is if you have localhost entries on the apache server for specfic host names
Examples
Localhost File
10.0.0.2 foo.bar.com
10.0.0.3 bar.bar.com
How it works
The client makes a request to foo.bar.com (dnslookup is a public IP... YOUR APACHE SERVER)
Your apache server has a localhost entry of 10.0.0.2 for foo.bar.com (some other server on your network)
The request goes through ModRewrite and /path1 is appended, then handed off to ProxyPass and ProxyPassReverse
ProxyPass and ProxyPassReverse hand the call off to foo.bar.com at ip 10.0.0.2
Client requests foo.bar.com ---reverse proxies to----> foo.bar.com/path1 (on some OTHER internal server)
Apache Configuration
<VirtualHost *:443>
Servername *
# Must not contain /path1 in path (will add /path1)
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/path1/.*
RewriteRule ^/(.*) https://%{HTTP_HOST}/path1$1 [NC,R=302,L]
# Must contain /path1 in path (will send request to the proxy)
RewriteEngine On
RewriteOptions Inherit
RewriteCond %{REQUEST_URI} ^/path1/.*
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [NC,P]
SSLEngine on
SSLProxyEngine On
ProxyRequests Off
ProxyPass / https://$1/
ProxyPassReverse / https://$1/
ProxyPreserveHost On
###################
# SSL Constraints #
###################
SSLProtocol -ALL +SSLv3 +TLSv1
# Choose cipher suites
SSLHonorCipherOrder On
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:!LOW:!SSLv2:!EXPORT
# SameOrigin The page can only be displayed in a frame on the same origin as the page itself
Header set X-Frame-Options SAMEORIGIN
SSLCertificateFile /etc/apache2/example.crt
SSLCertificateKeyFile /etc/apache2/example.key
SSLCertificateChainFile /etc/apache2/gd_bundle.crt
SetOutputFilter INFLATE;proxy-html;DEFLATE
</VirtualHost>

Just answering my own question:
I was missing 2 things:
the configuration should be:
RewriteEngine On
RewriteRule ^(.*)$ http://%{HTTP_HOST}$1 [P]
Not to forget to enable inherit in the virtual directory:
RewriteEngine On
RewriteOptions Inherit

You should read this page if you haven't done it already :
https://httpd.apache.org/docs/2.2/mod/mod_proxy.html#forwardreverse
I think the ProxyRequests directive is what you are looking for.

Related

How to Redirection and apply TLS with single web server multiple ports using RewriteEngine and ProxyPassReverse in Apache configuration

I'm running into a very serious problem.
Hope someone kind can help.
Please see the code below first.
This is part of my Apache configuration.
First, the URL of the target web server is http://localhost:30001 ~ 30010. Identifies the site to be accessed through each PORT.
When I receive input as "http://localhost/wksp/30001", I use RewriteEngine to make it "http://localhost:30001". This part works without any problems.
However, I tried to apply TLS and run "https" through ProxyPass and ProxyPassReverse again, but it is very difficult.
From what I understand, ProxyPassReverse accesses "http://localhost:[PORT]/" at first, but then communicates with Proxy through "https://localhost/".
Therefore, when communicating with the https protocol, the PORT cannot be dynamically acquired. For example, if http://localhost:30001 is the target, you need to communicate with the proxy server through port 30001.
In my code now, when HTTPS=on, PORT is written as 30001, but what I want is to keep holding the variable $1 when HTTPS=off.
If you have another approach, that's fine. lots of advice Thank.
<VirtualHost *:443>
...
SSLEngine On
ProxyPreserveHost On
SSLProxyEngine On
ProxyRequests Off
RequestHeader set Front-End-Https "On"
...
RewriteEngine On
RewriteRule ^/wksp/(.*) http://localhost:$1 [P]
ProxyPassReverse / http://localhost:$1
<Location />
Order allow,deny
Allow from all
RewriteEngine On
RewriteCond "%{HTTPS}" =off
RewriteRule ^:(.*) http://localhost:$1/ [P]
ProxyPassReverse http://localhost:$1/
RewriteCond "%{HTTPS}" =on
ProxyPass http://localhost:30001/
ProxyPassReverse http://localhost:30001/
</Location>
</VirtualHost>
If HTTPS=on, if you change the url port of ProxyPass and ProxyPassReverse to $1, the following error is displayed.
httpd[1584880]: AH00526: Syntax error on line 55 of /etc/httpd/conf.d/wksp-tls.conf:
ProxyPass Unable to parse URL: http://localhost:$1/

Apache split wildcard sub-domain for ProxyPass

I have Apache config where I would need to split the http host domain which includes dashed subdomain and build a new path using these 3 of these matching groups in proxy pass or rewrite rule.
Example urls:
kube-test-selfservice.example.com/app/
kube-staging-selfservice.example.com/app2/
Would need to proxied to:
balancer://kubernetes/test/selfservice/app/
balancer://kubernetes/staging/selfservice/app2/
It is important that the test and selfservice in this example are captured as these values change. kube can be hardcoded for distinguishing this host under.
I currently only have basic proxy setup, have tried multiple regex rewrites, but as I am not very familiar with apache, would like some advice on that part.
<VirtualHost *:443>
ServerName example.com
ServerAlias *.example.com
ProxyRequests Off
ProxyPreserveHost On
AddDefaultCharset Off
<Proxy "balancer://kubernetes">
BalancerMember http://192.168.1.244:30001 route=node1 timeout=600
</Proxy>
ProxyPass / "balancer://kubernetes/"
ProxyPassReverse / "balancer://kubernetes/"
</VirtualHost>
Please try this, i try to run below and it worked :
RewriteEngine On
RewriteCond %{HTTP_HOST} ^kube-([a-z0-9_]+.)?-([a-z0-9_]+.)?.example.com [NC]
RewriteRule "^/?(.*)" http://kubernetes/%1/%2%{REQUEST_URI} [R=301,L]
Used URL :
http://kube-test-selfservice.example.com/app/
URL Rewritten to :
http://kubernetes/test/selfservice/app/

Apache proxy pass all urls and rewrite only one specific url

I have a website running the Ghost Blog engine in the back end. I configured the subdomain blog.domain.com to proxy to ghost engine (localhost:2368) but I need to verify that subdomain in google search console so I need the blog.domain.com/googlefile.html to return a specific string (that same string is available at domain.com/googlefile.html). How do I do that?
My virtual host config:
ServerName blog.example.com
ServerAlias *.blog.example.com
#here is what I tried
#RewriteEngine On
#RewriteCond %{HTTP_HOST} blog\.example\.com
#RewriteRule googlefile.html https://example.com/googlefile.html
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:2368/
ProxyPassReverse / http://127.0.0.1:2368/
Btw. all domains are https.
The solution was to enable SSLProxyEngine so I can proxy https urls and also use mod_rewrite with proxy ignore url
SSLProxyEngine On # enable SSLProxyEngine
ServerName blog.example.com
ServerAlias *.blog.example.com
RewriteEngine On
RewriteCond %{HTTP_HOST} blog\.example\.com
RewriteRule googlefile.html https://example.com/googlefile.html [P]
ProxyPreserveHost On
ProxyPass googlefile.html ! # ignore the rewrited url
ProxyPass / http://127.0.0.1:2368/
ProxyPassReverse / http://127.0.0.1:2368/

ProxyPassReverse dropping HTTPS

On my home network, I have a web server and a DNS server. I have various other application servers that I have added redirects for so I can simply visit sites like myapplication.domain.com or www.domain.com/application to get to my various services. I have a Subsonic server running on another server, and my goal is to be able to visit https://subsonic.domain.com and get my Subsonic traffic served over SSL on my web server. Eventually I hope to access this from outside the home, which is why it's important to proxy the non-secured HTTP traffic over HTTPS, but for right now, I'm just trying to get it working at home.
When I visit https://subsonic.domain.com, I end up getting an "unable to connect" error. The address I appear to be redirected to is subsonic.domain.com/login.view. If I tack HTTPS onto the front of that URL, I get the login page I'm looking for. Once I log in again, however, the URL changes, I'm redirected, and I end up losing the HTTPS again an have to keep re-adding it. Obviously I am doing something wrong.
I have set up a VirtualHost for subsonic.domain.com and am trying to use ProxyPass and ProxyPassReverse to get the traffic redirected in the way I want. Here is my VirtualHost for this site:
<VirtualHost subsonic.domain.com:443>
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
ProxyRequests Off
ProxyErrorOverride Off
ProxyPreserveHost On
ServerAdmin webmaster#localhost
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://192.168.1.5:4040/
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>
SSL is definitely up and running with no problem. I have another identical virtualhost for another directory that works fine (redirects on https://www.domain.com/directory), so I'm not sure what the problem is here. After the ProxyPassReverse, the URL just seems to be losing the https:// part. If I add it in, the site works fine until I visit another page and https:// is lost again. If I visit the application server directly at http://192.168.1.5:4040, I have no issues whatsoever.
Any advice would be most welcome.
EDIT
A little clarification on what I'm trying to do. I want to have my Apache server doing all of my redirecting and handling all of my SSL requests. Basically, from the browser to the Apache server is HTTPS, the ProxyPass from the Apache server to the application server us unencrypted HTTP (which is fine, this is my internal network), the ProxyPassReverse from the application server to the Apache server is plain HTTP, then the Apache server sends out the traffic as HTTPS.
Here's another VirtualHost that does what I want for a different subdomain. This is tested and works 100%. I connect to my Apache server via HTTPS, the Apache server contacts my ownCloud server in plain old HTTP, the response to my Apache server is plain HTTP, then the Apache server returns the request in HTTPS to the browser:
<VirtualHost www.domain.com:443>
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
ProxyRequests Off
ProxyErrorOverride Off
ProxyPreserveHost On
ServerAdmin webmaster#localhost
ProxyPass /owncloud/ http://192.168.1.251/owncloud/
ProxyPassReverse /owncloud/ http://192.168.1.251/owncloud/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>
So I ran into this problem as well and while commenting out ProxyPreserveHost fixes the problem with the configuration above, there is a better way.
The ProxyPass1 statement tells Apache to take an incoming request on the URI and pass it through to the specified host. With ProxyPreserveHost On, Apache does not change the Host: HTTP header and passes the request unmodified. (By default it changes it to match the backend host specified in the ProxyPass statement).
The ProxyPassReverse2 statement tells Apache to match the host specified with the Host: header on the outgoing response and if it matches to adjust the Location:, Content-Location:, and URI: headers to match the VirtualHost or more specifically what Apache thinks is the canonical name.
So with the following configuration:
<VirtualHost subsonic.domain.com:443>
ProxyPreserveHost On
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://192.168.1.5:4040/
</VirtualHost>
This is taking a request:
https://subsonic.domain.com/ -> http://192.168.1.5:4040/
but since ProxyPreserveHost is on, it is leaving the Host: header in the request intact as subsonic.domain.com
Your web application is most likely sending a response from subsonic.domain.com but that does not match the ProxyPassReverse rule you have specified:
http://subsonic.domain.com/ <- http://subsonic.domain.com/
So the configuration:
<VirtualHost subsonic.domain.com:443>
ProxyPreserveHost On
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://subsonic.domain.com/ # Changed to match canonical host
</VirtualHost>
This rule should match the replies coming from the proxy host.
In my VirtualHost for Subsonic, I had to disable the ProxyPreserveHost On directive. I can now access the site externally and internally.
For some reason, this worked fine for my other VirtualHost, but for this one it did not. I'm assuming it's because in my one VirtualHost, the ProxyPass is working on a directory and not a hostname. In my VirtualHost for Subsonic, I don't specify a directory.
To anyone that actually knows what they're talking about in regards to Apache, VirtualHosts, redirects, etc, please feel free to clarify if I'm not describing accurately what's going on.
Here is my VirtualHost for anyone else that is experiencing this same issue.
<VirtualHost subsonic.domain.com:443>
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
ProxyRequests Off
ProxyErrorOverride Off
#ProxyPreserveHost On - This line now commented out
ServerAdmin webmaster#localhost
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://192.168.1.5:4040/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>

hosting multiple websites on apache under one ip address

I am trying to host multiple websites (app.diff1.com and app.diff2.com running on tomcat server) on my apache server which are running on ports 8082 and 8083 respectively, to access them i want to use a single domain name (app.in.xxx.com/diff) along with a differentiater (diff1/diff2).I used url rewriting to change the domain names respectively. Now when i am trying to access the websites i always end up with hitting the first virtual host.
Please suggest me if i am not approaching the solution correctly.
Code snippet:
in httpd.conf file.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^app\.in\.xxx\.com/([a-z]*)$
RewriteRule ^ http://www.app.%1.com [L,R=301]
</IfModule>
<IfModule mod_proxy.c>
ProxyRequests off
</IfModule>
NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.app.diff1.com
ProxyPass / http://www.app.diff1.com:8082/
ProxyPassReverse / http://www.app.diff1.com:8082/
</VirtualHost>
<VirtualHost *:80>
ServerName www.app.diff2.com
ProxyPass / http://www.app.diff2.com:8083/
ProxyPassReverse / http://www.app.diff2.com:8083/
</VirtualHost>
Move your rewrites into the first listed virtual host, and stop trying to capture the first path component of the URL as if it were part of HTTP_HOST -- capture it in the RewriteRule itself and use $1.
Also see ServerPath which is an esoteric way to do the same mapping.