AJP proxy that maps internal servlet name to a different external name - apache

Using apache2 I want to set up an AJP proxy for a Tomcat server that maps an internal servlet URL to a completely different URL externally. Currently I am using the following configurations:
Apache2 configuration:
<IfModule mod_proxy.c>
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
</IfModule>
Note that external_name and servlet_name are different.
Tomcat 6 configuration:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
This however does not work. Apache seems to forward http requests to Tomcat.
However the URLs and redirects returned by Tomcat are still using the original servlet_name and Apache does not map them to external_name.
Is this possible at all with AJP? If not can it be done using a plain http proxy instead?

Mapping different names between Apache and Tomcat can be quite tricky and depends much on how the web application builds its urls for the response.
Basically your setup is correct, but if your application uses its own servlet_name for redirects and urls ProxyPassReverse won't map them.
If you need this kind of setup have a look at mod_proxy_html (Apache 3rd party module) which will parse and rewrite also the contents, not only the url and response headers as mod_proxy.

( A late answer, but I just ran into this problem myself. )
It appears that ProxyPassReverse using ajp: doesn't work because the headers returned from a redirect don't have an ajp: URL in Location:, they have a http: URL. ProxyPassReverse just causes a rewrite of matching headers, and
that string doesn't match what's being returned.
This should work (provided the Location: field uses that numerical address
and not a host name.)
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
( You can use 'curl -I' to inspect the redirect headers and debug. )
See this note, or a more involved solution here using mod_proxy_html
for rewriting the URLs in web pages as well.

Additionally to the answer from Steven D. Majewski there is one more problem. If the target application uses the request host name to create a redirect (302 Moved Temporarily), it won't work with multiple host names. One must create multiple configurations for every name, like this:
ProxyPassReverse /external_name http://server.com/servlet_name
ProxyPassReverse /external_name http://server.org/servlet_name
ProxyPassReverse /external_name http://server.co.uk/servlet_name
Actually the ProxyPreserveHost on must solve this issue and replace the HOST header in the incoming requests with the address or IP specified in ProxyPass. Unfortunately it seems to be the ProxyPreserveHost doesn't work with ajp connectors. The tomcat in my configuration still received the host name got from browser instead replacing it with 192.168.1.30. As result the browser based redirects still didn't work for every name.
Following configuration didn't work as well :-(
# NOT WORKING !!!
ProxyPassReverse /external_name http://%{HTTP_HOST}/servlet_name
The workaround was using http instead of ajp.
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
Did somebody investigate it deeply?

For me, this seemed to cause problems:
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
While this seemed to work:
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
I don't know why but it just did.

Related

Hide Original URL using mod_proxy

I have been successfully able to use ProxyPass and ProxyPassReverse to reverse-proxy an application running under a Tomcat Server.
However, the challenge is that I want to use a fake URL, to obfuscate completely the path of the original application.
Let's say that my Apache Server is listening to port 9999, and the internal path of the original application is 192.168.1.55:8080/myapp.
Currently, I use ApacheIP:9999/myapp and it works just fine.
When I try to use a fake "alias", for example from myapp to business, Apache returns an HTTP error code (404).
Here's a very short extract of my httpd.conf:
ProxyPass /myapp http://192.168.1.55:8080/myapp Keepalive=On timeout=600
ProxyPassReverse /myapp http://192.168.1.55:8080/myapp

How to determine whether Apache is using as Forward Proxy or Reverse Proxy?

Apache can be used as Forward Proxy or Reverse Proxy, how to determine whether Apache is using as Forward Proxy or Reverse Proxy? I think it is configed in httpd.conf file, but I don't know which configuration field decide this.
ProxyPass and ProxyPassReverse are the directives that need to be configured to set up Apache as a reverse proxy.
In simple terms 'ProxyPass' performs unidirectional address space conversion from external to internal as in :
ProxyPass /app1/ http://internal1.example.com/
ProxyPass /app2/ http://internal2.example.com/
so http://www.example.com/app1/some-path maps to http://internal1.example.com/some-path as required.
while ProxyPassReverse performs the inverse translation from the app/web -server response to the externally address space as in :
ProxyPassReverse /app1/ http://internal1.example.com/
ProxyPassReverse /app2/ http://internal2.example.com/
this enables self-references/references to other internal servers to not pass through as-is but to be converted to external address spaces, in case of re-directs for example:
HTTP/1.1 302 Found
Location: http://internal.example.com/foo/
//ProxyPass lets this through to user browser as-is!
with Reverse Proxy this gets returned to the user's browser as
HTTP/1.1 302 Found
Location: http://www.example.com/foo/
using a ProxyPassReverse directive.

Apache ProxyPass to 2 different tomcat servers with same URI

I have 2 servers with apache http server (2.4.9) on them. I have 2 servers with tomcat 7.0.39 running on them. Ultimately I need to load balance between the 2, but right now am simply trying to get this ProxyPass configuration to work.
I have one url on the 2 apache servers- example.com. They are load balanced. The load balancing is in place and there is no issue.
I have 2 applications, 1 on each tomcat server. Each tomcat server has 2 instances of tomcat running- each on a different port. They are running a very similar application with the exact same uri.
I need to redirect:
example.com/site1 to example.com/app (for app1)
example.com/site2 to example.com/app (for app2)
I can redirect this easily enough for 1 application only:
ProxyPass /app/ AppSrv:8080/app/
ProxyPassReverse /app/ http://example.com/app/
I can get to the page, log in, no problem. For a singe application only.
When I set up a configuration for both applications, I can get to the login page of both applications as well when configured as such:
ProxyPass /site1/ AppSrv:8080/app
ProxyPassReserve /app/
ProxyPass /site2/ AppSrv:8081/app
ProxyPassReverse /app/
Both urls come up with the tomcat application login page. But neither work after this- they fail. The uri reads 'site1' (or 'site2') not 'app'. I cannot log in.
The application requires the uri '/app/' as the base uri in order to function.
The applications are listening on different ports, but have the same uri. How do I keep the uri in the url, but change it so the application responds?
Ultimately I have to balance this, but I've done that before. This is the part I'm having a hard time with.
Ok, I finally solved this. I had to modify the header.
ProxyPass /site1/ balancer://example.com/app/
ProxyPass /site2/ balancer://example.com/app/
<Location /site1>
ProxyPassReverse /app
ProxyPassReverseCookiePath /app /site1
Header edit Location ^(https?://)?example.com/app/ /site1/
</Location>
<Location /site2>
ProxyPassReverse /app
ProxyPassReverseCookiePath /app /site2
Header edit Location ^(https?://)?example.com/app/ /site2/
</Location>

ProxyPassReverse to Tomcat adding path to URL

I'm running Railo 3 in Tomcat 6.0.32. The tomcat server is fronted by Apache 2.2.20. Tomcat and Apache are pre built binaries from openCSW. Railo is just the latest build war deployed in tomcat's autodeploy dir webapps.
Everything is working fine when I try to access railo and content on the tomcat server.
It fails however, when railo on tomcat redirects me to itself. Mostly, when a cfm script uses the CGI.script_name, it will be returned wrong.
On the Apache side, the content is available on www.hostname.com. Apache redirects the user to tomcat through AJP on www.hostname.com:8009/railo/content.
A script on tomcat (taken from open OAuth example) is available at:
/opt/csw/share/tomcat6/webapps/railo/content/oauth_test/examples/admin_consumers.cfm
When I access it and try to perform some action, it calls itself with a few parameters, but at that point, railo dumps out an error, complaining that the file can not be found:
Page /content/railo/content/oauth_test/examples/admin_consumers.cfm [/opt/csw/share/tomcat6/webapps/railo/content/railo/content/oauth_test/examples/admin_consumers.cfm] not found
As you can see railo added twice the relative path from tomcat: /railo/content/railo/content
This is my configuration for the virtual host in Apache:
<VirtualHost *:443>
ServerName www.hostname.com
DocumentRoot "/opt/www/hostname/htdocs/"
ProxyRequests Off
<proxy *="">
Order deny,allow
Allow from all
</proxy>
ProxyPass / ajp://www.hostname.com:8009/railo/content/
ProxyPassReverse / http://www.hostname.com:8888/railo/content/
</VirtualHost>
I tried several variant for the ProxyPassReverse directive, but with no luck so far. Based on extensive searches on the web (The Mystery of ProxyPassReverse), I tried this for the proxypassreverse:
ProxyPassReverse / ajp://www.hostname.com:8009/railo/content/
ProxyPassReverse / http://www.hostname.com:8888/railo/content/
ProxyPassReverse / http://localhost:8888/railo/content/
ProxyPassReverse / https://www.hostname.com
The tomcat server also has a virtual host defined like this:
<Host name="www.hostname.com">
<Context path="" docBase="/opt/csw/share/tomcat6/webapps/railo/content" />
</Host>
But everytime, I always get the error from Railo.
Has anyone ever seen this problem with Railo, or CGI, and has an idea how to fix it?
You are specifying "/railo/content" twice. Once in your "docBase" attribute and again in your Proxy attributes. So, requests being proxied through Apache are going to have "railo/content/" twice in their request paths because you have it listed twice: once in Apache, another time in Tomcat.
Try leaving off the /railo/content/ in your ProxyPassReverse attribute:
ProxyPassReverse / http://www.hostname.com:8888/
This will let the Tomcat config add the /railo/content/ bit all by itself.

Multiple ProxyPassReverse for a Virtual Host with identical URLs

We have a situation where we have one JBoss application that is being proxied by two Apache paths as a Virtual Host below:
<VirtualHost *:80>
ServerName localhost1
ProxyPass /abba/ http://localhost:8080/app/
ProxyPass /babba/ http://localhost:8080/app/
ProxyPassReverse /abba/ http://localhost:8080/app/
ProxyPassReverse /babba/ http://localhost:8080/app/
</VirtualHost>
The routing of /abba/ and /babba/ need to go to the same application - going forward we are using rewrites to add some parameters that the application uses to configure itself based on whether /abba/ or /babba/.
However when the application sends a redirect the ProxyPassReverse does not work as access sayfrom /babba/ gets redirected to /abba/.
I understand the reason as it's the same application - however is there are way of configuring Apache to support two difference routes (ProxyPass and ReverseProxyPass) to the same application.
Many Thanks
Have you tried duplicating the VirtualHost and changing the duplicate to server name "localhost2"?