reverse proxy with SSL and url encoding, path change - apache

environment http://etrafficcontrol.com/misc/proxy.png
I have two applications. One is an e-commerce site (Drupal 7 running on LAMP) hosted on AWS, and the other is the checkout system which is ASP on IIS-6, is located inside our company, and requires SSL.
Currently we put up with the situation where our customers get forwarded to another domain for checkout -- kind of like what happens with ebay and PayPal. But this leads to difficulty with site tracking code, and kind of feels wrong for the shopper to get forwarded off of the e-commerce site for checkout.
The main concern is that we use Google campaigns, so we want to track conversions from advertising to, and rich content on, domain-1, but the actual sale happens at the time of checkout on domain-2.
Rather than send visitors from www.domain1.com/cart to domain2.com/miscX, I've tried to setup ProxyPass and ProxyPassReverse so I can send them to www.domain1.com/shop/miscX.
App1 (drupal) is in domain1.com/*, and the .htaccess stuff bypasses Drupal's design to intercept everything. The "misc" paths come from the fact that I'm redirecting into a subdirectory, and then proxying from there. When the proxied pages render, they have some hard-coded paths to /miscX, and without making special provisions for those during the rediects, I wind up with /miscX/ (instead of /shop/miscX/ which will follow the proxy) and that causes missing css, js, etc.
Note: Our business customers can login directly to domain2.com, so I'd like to keep that portal unchanged.
Below, local-d7 is a local test instance of the domain1 server. A test of the proxy shows that this concept works, with SSL.
I have this almost working, but it seems like URL-encoded parameters are being lost (even though query strings are ok). When I introduce the proxy, server2 doesn't appear see encoded params (it's a specialized app and I don't know how to view what IIS is receiving). When I route the domain2 test portal login thru apache on server-1 in such a way that doesn't have encoded params, the login works.
In effect I'm trying to
reverse proxy
change path (put an app running in / on domain-2 and expose into a subdir "/shop" on Domain-1
support SSL
proxy an IIS server behind Apache
try to not modify the IIS server so that it can continue to be used by it's original domain-2.com URL, and
do this on a hosted server where I [may] have limited configuration control of Apache. (currently testing on XAMPP).
I've tried all sorts of things in addition to what's shown here, including rewriterules, redirects, etc. I'm just not experienced at all at mod_proxy or mod_rewrite, etc. But it seems to me that this arrangement of a proxy should be doable with some amount of work and possibly fixing server SSL certificates.
Advice? --Thanks
vhosts.conf
## Redirect /misc1/ https://local-d7/shop/misc1/
## Redirect /misc2/ https://local-d7/shop/misc2/
## Redirect /misc3/ https://local-d7/shop/misc3/
## ProxyRequests Off
## ProxyPreserveHost On
## RequestHeader set Proxy-SSL true
## ProxyPass /shop/ https://www.shop.com/
## ProxyPassReverse /shop/ https://www.shop.com/
ProxyPass /shop/ https://www.domain2.com/
ProxyPassReverse /shop/ https://www.domain2.com/
ProxyPass /misc1/ https://www.domain2.com/misc1/
ProxyPassReverse /misc1/ https://www.domain2.com/misc1/
ProxyPass /misc2/ https://www.domain2.com/misc2/
ProxyPassReverse /misc2/ https://www.domain2.com/misc2/
ProxyPass /misc3/ https://www.domain2.com/misc3/
ProxyPassReverse /misc3/ https://www.domain2.com/misc3/
.htaccess
RewriteCond %{REQUEST_URI} ^/misc1/
RewriteCond %{REQUEST_URI} ^/misc2/
RewriteCond %{REQUEST_URI} ^/misc3/
RewriteRule (.*) /shop/$1

Related

.htaccess redirect to a new domain WITHOUT reload the page

Currently, I'm making a website and I would like this site to redirect (via .htaccess) to another domain WITHOUT reloading the page. Because in all the tutorials I saw, it loaded the page of the new domain. Outside what I want is that it keeps the page of the base domain while displaying the URL of the new domain.
Example:
redirect this site
https://DOMAIN1.US/folder1/folder2/page.html?param=1&param=2
to this site
https://DOMAIN2.US/folder1/folder2/page.html?param=1&param=2
i dont have the access to the main server config. Htaccess cannot "fake redirect" ??
What you are asking for is not a simple "redirect" (which is managed by the browser). You need to configure the server that hosts domain1.com as a "reverse proxy" - since this needs to be managed entirely server-side.
The user sends a request to domain1.com. The server at domain1.com then constructs an internal HTTP request (reverse proxy) to domain2.com. The response from domain2.com is then sent back to the server at domain1.com which then forwards the (possibly "rewritten") response back to the client.
This requires additional modules enabled on the server at domain1.com, ie. mod_proxy, mod_proxy_http and additional (optional) modules such as mod_proxy_html, etc. depending on your requirements.
Ideally, you would then configure this in the server config (or VirtualHost container). Notably, you would need to set ProxyPassReverse (in the server config) to cover the scenario of domain2.com issuing an external redirect to itself. The proxy server needs to rewrite the response headers so that the redirect goes to domain1.com, not domain2.com. ProxyPassReverse cannot be set in .htaccess.
You can then use mod_rewrite with mod_proxy by using the P flag. This part you can do in .htaccess. For example, to proxy the request from https://DOMAIN1.US/folder1/folder2/page.html?param=1&param=2 to https://DOMAIN2.US/folder1/folder2/page.html?param=1&param=2.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.us [NC]
RewriteRule ^ https://domain2.us%{REQUEST_URI} [P]
If you have access to the server config then you can do this more simply with the ProxyPass directive (no need for mod_rewrite in this instance since the source and target URLs are the same).
Reference:
https://httpd.apache.org/docs/2.4/mod/mod_proxy.html

Apache Conditional Redirect Rule not forwarding header values

Goal:
To perform conditional redirect/forward from Site1 to Site2 based on specific header (HTTP_SM_USER) value of the request (in Site1) and ensure all the current custom header data is forwarded as part of the redirect/forward to Site2. The user can see the url change in the browser window after the redirect.
Flow:
User accesses Site 1 --> External Application Sets few custom headers in addition to default HTTP headers based on certain criteria --> Web-server looks for specific header value and if matches redirect all the headers to Site 2.
Apache Web server Config:
<VirtualHost *.443>
ServerName site1.com
ServerAdmin ashish#test.com
UseCanonicalName on
DocumentRoot /var/www/html
#
# SSL Config comes here
#
ErrorLog /path/to/error/log
TransferLog /path/to/access/log
LogLevel warn
RewriteEngine On
RewriteCond %{HTTP:SM_USER} ^USER1$ [NC]
RewriteRule .* https://site2.com/$1 [R=301, L]
<Location /page1>
.
.
</Location>
.
.
.
</VirtualHost>
Question: The Conditional Redirect happens but the headers are lost. What should I do to ensure the HTTP headers are forwarded as well ? I tried to see into apache mod_proxy but wasn't sure how in this scenario to use it. Experts please help. Any alternative suggestions are welcome too.
Solution:
I finally got it to work (with mod_proxy) after a lot of troubleshooting using the below flags and proxy rules. All Rewrite rules were removed.
ProxyRequests Off
ProxyPreserveHost On
SSLProxyEngine On
ProxyPass "/" "https://site2.com/" Keepalive=On
ProxyPassReverse "/" "https://site2.com/"
Note: User accesses Site 1 -> External app sets headers and apache immediately proxies to Site 2. Headers are now available on Site2.
You can't have the redirect "forward" headers, because it is up to the client what it sends to the next server after it has been issued a redirect. It may choose not to follow the redirect at all! Unlikely but just to make it clear what the situation is.
If you want the URL to change in the browser, then you need to do this on the application side. Have your application handle directing to the next server, and just issue a 200 response with an instruction for it to do so. Then it can send the custom headers as it did with the first request.
If that is not acceptable, then using mod_proxy could work as you said, but it would not change the URL in the browser, because the first server would be proxying the request to the second, so the browser would still see it as being the first.
In summary, you cannot do what you want to do, because HTTP does not work that way, so you are going to have to compromise in some way, either by not changing the URL in the browser, or by updating the application to take care of it.

Reverse proxy with request dispatch (to Rstudio server)

I have a multi-tier application of three layers lets say public, business and workspace (all running apache).
Client requests hits the public servers, requests are processed and dispatched on to business servers that does 'things' and response is returned back to public server which then processes the response and pass it on to the client.
I have a scenario wherein I want a request say /rstudio coming to the public server dispatched onto the business which intern reverse proxy to workspace server. There are two catch here:
the workspace server varies per request
application running on workspace server (Rstudio) uses GWT and references resources (static resources js, css etc and RPC coms) on the root url. All the in-application redirection also happens on the domain.
From the business server, I have setup reverse proxy to Rstudio server from my application server.
<Proxy *>
Allow from localhost
</Proxy>
ProxyPass /rstudio/ http://business_server/
ProxyPassReverse /rstudio/ http://business_server/
RedirectMatch permanent ^/rstudio$ /rstudio/
and this work fine (ref. https://support.rstudio.com/hc/en-us/articles/200552326-Running-with-a-Proxy). To handle dynamic workspace server, I could the following but ProxyPassReverse does not support expression in value and this no joy with this approach.
ProxyPassMatch ^/rstudio/(.*)$ http://$1
ProxyPassReverse ^/rstudio/(.*)$ http://$1
RedirectMatch permanent ^/rstudio$ /rstudio/
I have tried the same with mod_rewrite rule (following) but without ProxyPassReverse and due to domain redirection on the GWT Rstudio, this does not work. Adding ProxyPassReverse would fix the problem but I am caught up with no expression on value part to deal with dynamic workspace server issue.
RewriteRule "^/rstudio/(.*)" "http://$1" [P]
Following is the third approach to solve this problem using LocationMatch and mod_headers:
<LocationMatch ^/rstudio/(.+)>
ProxyPassMatch http://$1
Header edit Location ^http:// "http://%{SERVER_NAME}e/rstudio/"
</LocationMatch>
But this is no joy too because value on header directive is not evaluated against environment variable (and only back-references work here). Althought I can get the reverse proxy thing working if I had code the business_server, which is :
<LocationMatch ^/rstudio/(.+)>
ProxyPassMatch http://$1
Header edit Location ^http:// "http://private_server/rstudio/"
</LocationMatch>
Question 1: I was wondering if there are any better way to solve this problem without hardcoding the server DNS in apache conf?
Question 2: With the hard coded server DNS the reverse proxy works for me (patchy but works) but I am hit with GWT issue of resource references on root and the request dispatch is not fully working. I get to the signin page but resources are not found.
I was wondering if there is any better way to handle that?
Following is the example log from browser:
Navigated to https://public_server/rstudio
rworkspaces:43 GET https://public_server/rstudio.css
rworkspaces:108 GET https://public_server/js/encrypt.min.js
rworkspaces:167 GET https://public_server/images/rstudio.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonLeft.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonTile.png 404 (Not Found)
rworkspaces:218 GET https://public_server/images/buttonRight.png 404 (Not Found)

Apache 2.2 Mod Proxy ProxyPass behavior

I have a server server.example.com which serves Tomcat on port 80 via a ProxyPass/ProxyPassReverse to 8080 and a Drupal site on the same box at server.example.com:8001. If I enter in the port 8001 explicitly, the Drupal site behaves properly, but I need to make it accessible via server.example.com/blog so I created a ProxyPass/ProxyPassReverse for /blog http://server.example.com:8001 which serves the initial page for the Drupal site correctly, but once the form on the home page of Drupal is filled out and submitted, which POSTs to /, the site changes to the Tomcat site, presumably because the / is not relative to the current host on post :8001. How can I get the ProxyPass for /blog to remain persistent so that all subsequent requests remain within the :8001 VirtualHost (Drupal site)?
One thing I tried was with mod_rewrite:
RewriteCond %{HTTP_REFERER} /^blog/.*$
RewriteRule (.*) %{HTTP_HOST}:8001/$1 [L,P,NC]
But that did nothing at all as far as I can tell. I was hoping that if the initial request was for /blog then the referrer would be as well and I could keep requests on the :8001 virtualhost. Perhaps someone can explain why that is flawed.
The problem you are very likely running into is that the documents returned by Drupal include generated links that all reference / instead of /blog. mod_rewrite and proxypass don't do anything to the contents of documents -- they only act upon the request (or, in the case of ProxyPassReverse, on links such as Location: headers in returned content).
To make an application that normally expects to be installed as / operate on a different URL, you need either to :
(a) Configure the application to be aware of the proper base URL. Many applications include such a setting in order to support exactly the situation you have described.
(b) Install some sort of filtering proxy that can modify the content of returned documents. For Apache, mod_proxy_html is made to do exactly this. This is included natively in Apache 2.4 but may need to be installed separately for 2.2.

Apache - Reverse Proxy and HTTP 302 status message

My team is trying to setup an Apache reverse proxy from a customer's site into one of our web applications.
http://www.example.com/app1/some-path maps to http://internal1.example.com/some-path
Inside our application we use struts and have redirect = true set on certain actions in order to provide certain functionality. The 302 status messages from these re-directs cause the user to break out of the proxy resulting in an error page for the end user.
HTTP/1.1 302 Found
Location: http://internal.example.com/some-path/redirect
Is there any way to setup the reverse proxy in apache so that the redirects work correctly?
http://www.example.com/app1/some-path/redirect
There is an article titled Running a Reverse Proxy in Apache that seems to address your problem. It even uses the same example.com and /app1 that you have in your example. Go to the "Configuring the Proxy" section for examples on how to use ProxyPassReverse.
The AskApache article is quite helpful, but in practice I found a combination of Rewrite rules and ProxyPassReverse to be more flexible. So in your case I'd do something like this:
<VirtualHost example>
ServerName www.example.com
ProxyPassReverse /app1/some-path/ http://internal1.example.com/some-path/
RewriteEngine On
RewriteRule /app1/(.*) http://internal1.example.com/some-path$1 [P]
...
</VirtualHost>
I like this better because it gives you finer-grained control over the paths you're proxying for the internal server. In our case we wanted to expose only part of third-party application. Note that this doesn't address hard-coded links in HTML, which the AskApache article covers.
Also, note that you can have multiple ProxyPassReverse lines:
ProxyPassReverse / http://internal1.example.com/some-path
ProxyPassReverse / http://internal2.example.com/some-path
I mention this only because another third-party app we were proxying was sending out redirects that didn't include their internal host name, just a different port.
As a final note, keep in mind that Firebug is extremely useful when debugging the redirects.
Basically, ProxyPassReverse should take care of rewriting the Location header for you, as Kevin Hakanson pointed out.
One pitfall I have encountered is missing the trailing slash in the url argument. Make sure to use:
ProxyPassReverse / http://internal1.example.com/some-path/
(note the trailing slash!)
Try using the AJP connector instead of reverse proxy. Certainly not a trivial change, but I've found that a lot of the URL nightmares go away when using AJP instead of reverse proxy.