[Edit] - Thanks for the comments. I've tried to shape my question accordingly and I've added some additional information based on the suggestions offered.
I have a JSF web application running on JBoss AS7 that I front with Apache on SSL (port 443). Apache and JBoss are running on the same machine and communicate "in the clear" over HTTP with reverse proxy forwarding rules. With this setup, I have observed that clicking on any link created via the JSF tag <h:commandLink> (i.e. without <f:ajax> and where there is always a genuine backing bean action method that, after performing some business logic, returns an outcome with the ?faces-redirect=true suffix) will see the page redirect fail because the https scheme is dropped and replaced with http.
If I replace all instances of <h:commandLink> with <h:commandLink><f:ajax/></h:commandLink>, this redirection problem goes away - i.e. the https scheme is preserved in the resulting redirected URL.
Could anyone explain to me what I'm observing and what the "under-the-hood" difference between the non-ajax form submit and ajax submit might be in this case?
Additional Information:
My Apache reverse proxy rules:
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order Allow,Deny
Allow from all
</Proxy>
ProxyPass / http://localhost:8080/ timeout=1800
ProxyPassReverse / http://localhost:8080/
The web console in Firefox shows the difference between the ajax form submit and non-ajax form submit HTTP requests as:
Ajax submit via <h:commandLink><f:ajax/></h:commandLink>
I see a GET request to the expected page on https (I can't yet post screen shots)
Non-ajax submit via <h:commandLink/>
The non-ajax version first POSTs back to the same page (which is expected) on https with a 302 status code 'Moved Temporarily' and then redirects to the target page from the action method on http.
Location in HTTP header for POST before failed GET redirect on http
Here's a screen shot. The location value for the POST shows as the URL of the GET request, on http and not https:
I guess I've gotten slightly "under-the-hood" at this point. Since the <f:ajax> approach achieves the desired result, I am happy leaving this alone. It seems there are at least a few other JSF posts related to this same sort of thing (here's the single URL I'm allowed to post):
JSF redirects from HTTPS to HTTP
Maybe the ajax-based approach is required to preserve the scheme in the URL originating from the client?
Thanks,
-Andy
Related
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)
I have Proxy Pass somewhat working. I am using it like so
ProxyPass /chorus/ http://localhost:7070/
ProxyPassReverse /chorus/ http://localhost:7070/
This chorus folder does not exist and I am accessing through apache port 80 in the browser. Then it redirects to my application running on port 7070 which provides its webpage. The functionality within the webpage does not work though because the javascript starts requesting images and other info as /images/image1.jpg for example or /jsonrpc on apache and isn't going through the proxy. But on port 80 there is no /images because it's part of the :7070 application. If I do like below it will work too, but there are too many folders, I need a way to set everything returned from 7070 to be processed by apache as http:// localhost:7070/image/...
ProxyPass /jsonrpc http://localhost:7070/jsonrpc
ProxyPass /image http://localhost:7070/image
Basically the page for the app loads but the content does not, the app is requesting /jsonrpc which looks something like this (proxied version)
Remote Address:192.168.1.150:80
Request URL:http://192.168.1.150/jsonrpc?tm=1419196786193
Request Method:POST
Status Code:404 Not Found
When in the app directly without proxy it looks like this
Remote Address:192.168.1.150:7070
Request URL:http://192.168.1.150:7070/jsonrpc?tm=1419196894248
Request Method:POST
Status Code:200 OK
it's not really something you can fix within the Proxy module, other than by spelling out all possible paths, which you want to avoid; your alternatives are:
a. change the application and make it proxy aware so that
a1. it produces paths by prefixing it with a configured path
a2. interprets something like a X-Forwarded-Path header
a3. uses the HTML base tag: http://www.w3schools.com/tags/tag_base.asp
b. change the proxy so that your app lives on it's own vhost e.g. chorus.example.org
I have 3 machines.
One (loadbalance.lan) is used as a load balancer, the other two (172.16.30.5 and 172.16.30.6) are tomcat's servers. Main page of the tomcat is listening on port 8080
Im typing in the browser loadbalance.lan/tomcat and I am able to see one of the tomcat content (default tomcat page)
The problem is page isn't displayed correctly. There's no images and when I click on any link it displays 404 Not found error.
Lets say I want to access one of the sub pages on the tomcat website. Tomcat website address: 172.16.30.5:8080
Now I can choose, lets say "status" link which redirects me to: 172.16.30.5:8080/manager/status (and works fine)
When I access the same page but via reverse proxy server (loadbalance.net) and click that link on the loadbalance.lan page, links redirect me to loadbalance.lan/manager/status and I get 404 error.
Of course when I type in the browser loadbalance.lan/tomcat/manager/status it displays correct.
Problem with the images is also weird. When I use url: loadbalance.lan/tomcat I can't see images (Tomcat logo)
When I use this one: loadbalance.lan/tomcat/ (slash at the end) it's ok. At least images because links still redirect in wrong place.
Here is my loadbalance.lan apache config:
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<VirtualHost *:80>
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy balancer://cluster>
Order Deny,Allow
Allow from all
</Proxy>
<Proxy balancer://cluster>
BalancerMember http://172.16.30.5:8080
BalancerMember http://172.16.30.6:8080
<Proxy balancer://cluster>
</Proxy>
<Location /tomcat>
ProxyPass balancer://cluster
ProxyPassReverse balancer://cluster
</Location>
</VirtualHost>
Could someone help me with this?
Obviously there is something wrong with that proxy but I have no idea how to fix that :(
From ProxyPassReverse documentation (strong added):
This directive lets Apache adjust the URL in the Location, Content-Location and URI headers on HTTP redirect responses. This is essential when Apache is used as a reverse proxy (or gateway) to avoid by-passing the reverse proxy because of HTTP redirects on the backend servers which stay behind the reverse proxy.
Only the HTTP response headers specifically mentioned above will be rewritten. Apache will not rewrite other response headers, nor will it rewrite URL references inside HTML pages. This means that if the proxied content contains absolute URL references, they will by-pass the proxy. A third-party module that will look inside the HTML and rewrite URL references is Nick Kew's mod_proxy_html.
So, the proxy job is not to rewrite the html content of the pages, if the proxyied content does not know that the final url should contain /tomcat extension and the proxy does not alter the pages... you're stuck.
This is usually something you do not see because the 172.16.30.5:8080 part is well rewritten in localhost.lan, but this rewrite is not made by the proxy, quite certainly because urls are in fact only relative (<img src="/foo/bar.png">). Check the source code of the page to see if the domain name is really rewritten in urls).
There's several ways of handling that:
- You could avoid altering relative urls paths in, the proxy (so not using a tomcat/ prefix, but instead a dedicated virtualhost with a name, like tomcat.lodabalncer.lan).
- You could also use some dedicated tools, like mod_proxy_html to rewrite the content of the pages, but that's a slow and complex thing.
- The third way is to manage the final full url on the application side (here tomcat) and detect the proxy chain elements in X-Forwareded-for Header to rebuild the right domain.
- Some applications provides tools for that, like the VirtualHostMonster in Zope
For tomcat the preferred tool is mod_proxy_ajp and not mod_proxy. But for a load balancer proxy I do not think you can use mod_proxy_ajp. And, it's been a long time since I made this, but in my memory I think mod_jk was the solution to that.
Read this full documentation on tomcat proxying for details. At least you should get some hints for the solution.
I have Apache installed on my server and I need to redirect from http to https. The reason for this is our load balancer solution cannot hand https so requests come in on http and then we transfer them to https using the below lines in the httpd.conf file.
<VirtualHost 10.1.2.91:80>
Redirect 302 /GladQE/link https://glad-test.com/GladQE/link.do
</VirtualHost>
This works fine for GET requests but POST requests will lose the parameters passed on the URL. What would be the easiest way to perform this redirect and maintain POST params?
I need to get from http://glad-test.com/GladQE/link.do to here https://glad-test.com/GladQE/link.do maintaining POST params
Thanks
Tom
You can try with the HTTP status code 307, a RFC compilant browser should repeat the post request.
Reference: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
In contrast to how 302 was historically implemented, the request
method is not allowed to be changed when reissuing the original
request. For instance, a POST request should be repeated using another
POST request.
To change from 302 to 307, do that:
<VirtualHost 10.1.2.91:80>
Redirect 307 /GladQE/link https://glad-test.com/GladQE/link.do
</VirtualHost>
Standard Apache redirects will not be able to handle POST data as they work on the URL level. POST data is passed in the body of the request, which gets dropped if you do a standard redirect.
You have an option of either using a PHP script to transparently forward the POST request, or using a combination of Rewrite (mod_rewrite) and Proxy (mod_proxy) modules for Apache like follows:
RewriteEngine On
RewriteRule /proxy/(.*)$ http://www.example.com/$1 [P,L]
P flag passes the request to the Proxy module, so anything that comes to your site (via GET or POST doesn't matter) with a URL path starting with a /proxy/ will transparently be handled as a proxy redirect to http://www.example.com/.
For the reference:
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
http://httpd.apache.org/docs/current/mod/mod_proxy.html
Either your public facing website MUST use SSL to protect confidentiality or there is no sensitive data enver passing through it, and no possibility that your site will ever be used for a lauinchboard for sslstripping (there's a very good reason why Google serve up search results over HTTPS).
If you are not encrypting traffic between browser and your site then why are you trying to encrypt them between your load balancer and your webserver? If you do happen to have a SSL termination outside the load balancer (a very silly approach) then using HTTPS between the load balancer and the webserver is far from efficient. The question also implies lots of other security problems like session fixation/sniffing and SSLStripping vulnerabilities.
We currently have Apache/ WAS setup and I want the Apache to handle the static content and it is working as expected.
My question:
We have always used www.xxx.com before and WAS used to handle the page, now we want to WEB server to handle the page and route www.xxx.com to www.xxx.com/index.jsp without the user knowing about it.
We want to user to type in www.xxx.xom in the url and get to the WAS through Apache.
If I get you correctly, you want a reverse proxy for dynamic content of your website. Apache has the mod_proxy that allows you to do that for selective URLs. The ProxyPass directive allows you to specify what URLs are mapped to which HTTP servers. HTTP headers are modified accordingly that the external information can reach the WAS that is hidden behind your Apache. IIRC, WAS can be configured to be aware of the reverse proxy.
Reverse proxy based on a prefix:
ProxyPass /mirror/foo/ http://backend.example.com/
Reverse proxy based on a regex:
ProxyPassMatch ^(/.*\.gif)$ http://backend.example.com$1