Apache ProxyPassReverse fallback when host is down - apache

I have been unable to find any documentation to conclusively confirm or deny this apparent mod_proxy behaviour.
We have a web reverse proxy with multiple ProxyPassReverse definitions, similar to this:
ProxyPass /foo http://fooserver/
ProxyPassReverse /foo http://fooserver/
ProxyPass / http://barserver/
ProxyPassReverse / http://barserver/
As expected, requests for URLs under /foo go to fooserver, and all other requests get sent to barserver.
Recently, fooserver was shut down for other reasons. Users noticed that - sometimes - requests for /foo/xxx were incorrectly being routed to barserver which responded with a 404 (we know it was barserver responding because it runs a different webserver software).
My question is this - is it deliberate that ProxyPassReverse will fall back to a lower-priority route if the destination server is down, and if so, under what conditions does this fallback happen? I know that you can use mod_balancer if you want it to happen. I'm more interested in why it is happening this time when I had not expected it to, and any pointers to relevant documentation.

Related

Jenkins behind Apache Server / Can't log in Jenkins

I'm running an Apache Server 2.2 to handle Jenkins and SonaType Nexus information (both installed as Windows Service). While SonatypeNexus runs perfectly Jenkins doesn't. To be more specific: I'can't log in Jenkins. Just for your notice: we are using LDAP to login, but this can't be the reason for login failure, as login from local host works.
If I try to log in Jenkins from localhost:8071 it works perfectly.
When I log in from another system via network (using https://myServer.com:8095/) I can browse and configure Jenkins, but I can't login. Whenever I try I get "redirected" to the page of Jenkins I was on before hitting the "login" button.
Security settings are set to "everyone can do anything" -> can't be the reason either.
Hint 0: As you maybe already noticed we are using https for for any request from the outside dedicated to the server. But within the server Apache only uses http to handle information -> could this lead to problems?
Hint 1: I only get "redirected" using correct login parameters. Using wrong ones is leading me to the "Invalid login information. Please try again." page.
Hint 2: Sonatype Nexus is running behind the same Apache Server and works great.
Potentional Reason: guess the reason why I can login via localhost, but not via network must be our Apache 2.2 server which is handling information wrong. By using localhost I can bypass Apache (-> works) but via network Apache gets used (-> don't work).
Any ideas how to fix this or at least what the reason could be?
Here are some settings from apache server (httpd-ssl.conf) that maybe could be useful:
<VirtualHost *:8095>
ServerName myServer.com
ServerAdmin admin#myServer.com
# Nexus via HTTPS.
ProxyPass /nexus http://localhost:8072/nexus
ProxyPassReverse /nexus http://localhost:8072/nexus
ProxyPassReverseCookiePath / /nexus
RequestHeader set X-Forwarded-Proto "https"
ErrorLog logs/nexus_error_ssl.log
CustomLog logs/nexus_access_ssl.log common
# Jenkins via HTTPS.
ProxyPass / http://localhost:8071/ nocanon
ProxyPassReverse / http://localhost:8071/
ProxyPassReverse / http://my.host.com/
# also tested second ProxyPassReverse with specific port
ProxyPassReverseCookiePath / /
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
ProxyRequests Off
AllowEncodedSlashes NoDecode
SSLEngine on
I'm not sure if i describe my solution correct, since my collegue found the answer and not me.
Since the Apache was handling https (incomming from jenkins) correctly (requests reached LDAP), but was unable to pass http information (incomming from LDAP) correctly (login was unable).
So he took a look at the http settings and configured the settings to enable http. This was leading to our goal -> we can login now, BUT it also leads towards another problem -> http is enabled and usable for users...
On this page, it hints that you might need to add another ProxyPassReverse to fix http links generated by Jenkins:
ProxyPassReverse / http://your.host.com:8095/
Also, it mentions that you should add
ProxyPreserveHost On
to your config. Please check the link for further information.

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>

Stuck with apache,mod-ajp weird redirection

hi all i have a redirection problem with mod ajp, that it always adds the application name before the desired page, for example:
if i requested the page:
http://myapp.com/mypage
it is converted to
http://myapp.com/myapp/mypage, and i get a 404 error
i don't know why such behaviour occurs, this is the configuration:
<Proxy *> AddDefaultCharset Off Order deny,allow Allow from all </Proxy>
ProxyPass / ajp://127.0.0.1:8009/myapp/
ProxyPassReverse /
ajp://127.0.0.1:8009/myapp/
ProxyPassReverseCookiePath /myapp/
this strange redirection occurs exaclty when an inside application redirection occurs meaning after registration the user is redirected(application side) to the login page using response.sendRedirect , any ideas ?
The ProxyPassReverse directive is possibly wrong. I guess it should be
ProxyPassReverse / http://myapp.com
See The Mystery of ProxyPassReverse.
You can resolve problems like this with this approach:
Install LiveHTTPHeaders and enable it
Access the application directly
Access the application via your reverse proxy
Compare the HTTP traffic of the previous cases
Most likely your application redirects user using relative URL. However your ProxyPassReverse only rewrites absolute versions. The relative version gets redirected with the page load according to your ProxyPass rule, causing the doubling of the path.

Subdirectory on a different host

I've got a site www.example.com on one server. I'd like to create www.example.com/blog on another server/host.
A) Can I do this?
B) How can I do this?
I've read a bit on using Apache's mod_proxy, proxypass, and ProxyPassReverse, but I'm not gifted enough with Apache or server mgt to know if I'm on the right track or not. Or, if there are other options to doing what I want.
To be clear, I do not want a subdomain like blog.example.com. I know how I COULD do that with DNS, but I don't believe DNS is an option for subdirectories.
This is not doable nicely IMO. As you say, you would need a proxy based solution that fetches the content from the blog server and serves it to the user.
That has the serious downside that any traffic on your blog will have to run through your primary host, eating up bandwidth, resources and traffic volume.
Is a redirect (i.e. www.domain.com/blog doing a header redirect [visible in the browser's address bar] to blog.otherhost.com) an option?
If not, check out the documentation on mod_proxy. The basic example for a reverse proxy looks good already:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass /foo http://foo.example.com/bar
ProxyPassReverse /foo http://foo.example.com/bar

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

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.