16

I'm deploying Apache in front of a Karaf-hosted application (Apache and Karaf are on separate servers). I want Apache to operate as a reverse proxy and also to hide part of the URL.

The URL to get the log-in page of the application directly from the app server is http://app-server:8181/jellyfish. Pages are served by the Jetty instance running within Karaf. Of course, this behaviour would usually be blocked by the firewall for everything except the reverse proxy server.

With the firewall off, if you hit this URL then Jetty loads the log-in page. The browser's address bar correctly changes to http://app-server:8181/jellyfish/login?0 and everything works.

What I want is for http://web-server (i.e. from the root) to map to Jetty on the app server with the name of the app (jellyfish) suppressed. e.g. The browser would change to show http://web-server/login?0 in the address bar and all subsequent URLs and content would be served with the web-server's domain and without the jellyfish clutter.

I can get Apache to operate as a simple reverse proxy, using the following config (snippet):-

ProxyPass /jellyfish http://app-server:8181/jellyfish
ProxyPassReverse / http://app-server:8181/

...but this requires the browser's URL to contain jellyfish and going to the root URL (http://web-server) gives a 404 Not Found.

I've spent a lot of time trying to use mod_rewrite with and without its [P] flag to get around this, but without success. I then tried the ProxyPassMatch directive, but I can't seem to get that quite correct either.

Here's the current config, as is loaded into /etc/apache2/sites-available/ on the web server. Note that there is a locally-hosted images directory. I've also kept the mod_rewrite proxy exploit protection and am suppressing a couple of mod_security rules that were giving false positives.

<VirtualHost *:80>
    ServerAdmin admin@drummer-server
    ServerName drummer-server

    ErrorLog ${APACHE_LOG_DIR}/error.log
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined

    Alias /images/ "/var/www/images/"

    RewriteEngine On
    RewriteCond  %{REQUEST_URI}  !^$
    RewriteCond  %{REQUEST_URI}  !^/
    RewriteRule  .*              -    [R=400,L]

    ProxyPass /images !

    ProxyPassMatch ^/(.*) http://granny-server:8181/jellyfish/$1
    ProxyPassReverse / http://granny-server:8181/jellyfish

    ProxyPreserveHost On

    SecRuleRemoveById 981059 981060

    <Directory "/var/www/images">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
    </Directory>

</VirtualHost>

If I go to http://web-server, I get redirected to http://web-server/jellyfish/home but this gives a 404, with a complaint about trying to access /jellyfish/jellyfish/home - NB the browser's address bar does not contain the double /jellyfish.

HTTP ERROR 404

Problem accessing /jellyfish/jellyfish/home. Reason:

    Not Found

And, if I go to http://web-server/login, I get redirected to http://web-server/jellyfish/login?0 but this gives a 404, with a complaint about trying to access /jellyfish/jellyfish/login.

HTTP ERROR 404

Problem accessing /jellyfish/jellyfish/login. Reason:

    Not Found

So, I'm guessing I'm somehow passing through the rules twice. I am also slightly bemused as to where the home bit of the URL comes from in the first example.

Can someone point me in the right direction, please?

Thanks, J.

Jeremy Gooch
  • 423
  • 1
  • 4
  • 11
  • I've made some progress on this, and have now replaced `ProxyPassMatch` with an equivalent using `mod_rewrite`, which addresses the challenge of removing `jellyfish` from the URLs. I'm now looking into a number of 404s that then pop up with regard to underlying elements such as Wicket components required by Karaf. Here's a code snippet: `# proxy to the Jellyfish server (ignoring images) RewriteCond %{REQUEST_URI} !^/(images)(.*)$ RewriteRule ^(/.*)$ http://app-server:8181/jellyfish$1 [P] ProxyPassReverse / http://app-server:8181/jellyfish/` – Jeremy Gooch Nov 11 '13 at 16:31

2 Answers2

13

This is how I got it to work. As well as the changes as per my comment to my original question, I needed to exclude .js and .css from the rule that added a trailing slash.

<VirtualHost *:80>
    ServerAdmin admin@localhost
    ServerName mydomain.com
    ServerAlias www.mydomain.com

    ErrorLog ${APACHE_LOG_DIR}/error.log
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined

    RewriteLog ${APACHE_LOG_DIR}/rewrite.log
    RewriteLogLevel 9

    Alias /images/ "/var/www/images/"

    RewriteEngine On

    # rewrite rule to prevent proxy exploit
    RewriteCond  %{REQUEST_URI}  !^$
    RewriteCond  %{REQUEST_URI}  !^/
    RewriteRule  .*              -    [R=400,L]

    # consolidate non-www requests onto the www subdomain
    RewriteCond  %{HTTP_HOST}    ^yourdomain\.com$
    RewriteRule  ^(.*)           http://www.yourdomain.com/$1  [R=301,L]

    # Add a trailing slash to the URL (ignoring images, CSS and JavaScript)
    RewriteCond  %{REQUEST_URI}  !^/(images)(.*)$
    RewriteCond  %{REQUEST_URI}  !^/(.*)(.js|.css)$
    RewriteCond  %{REQUEST_URI}  !(.*)/$
    RewriteRule  ^(.*)$          http://%{HTTP_HOST}$1/ [R=301,L]

    # proxy to the Jellyfish server (ignoring images)
    RewriteCond  %{REQUEST_URI}  !^/(images)(.*)$
    RewriteRule  ^(/.*)$         http://app-server:8181/jellyfish$1  [P]
    ProxyPassReverse  /          http://app-server:8181/jellyfish/

    # suppress mod_security rules that were giving false positives
    SecRuleRemoveById 981059 981060

    <Directory "/var/www/images">
            Options Indexes MultiViews FollowSymLinks
            AllowOverride None
            Order allow,deny
            Allow from all
    </Directory>

</VirtualHost>
Jeremy Gooch
  • 423
  • 1
  • 4
  • 11
1

Have you tried:

ProxyPassMatch ^/(.*) http://granny-server:8181/$1
ProxyPassReverse / http://granny-server:8181

Or even more simply:

ProxyPass / http://granny-server:8181/
ProxyPassReverse / http://granny-server:8181/

I wrote up how I deal with Apache reverse proxying and Tomcat over here if you want to compare/contrast what you setup with what I use.

You might want to add this to add a trailing slash to the URL:

# Settings for adding a trailing slash to the URL
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^(.*)$ http://%{HTTP_HOST}$1/ [R=301,L]
Giacomo1968
  • 3,522
  • 25
  • 38
  • Many thanks for the reply. Unfortunately, this only resolves the straightforward proxying part of the problem. The bit I'm missing is how to remove the word "jellyfish" from visibility in the client's browser address bar, such that `http://web-server` silently gets proxied to `http://app-server:8181/jellyfish` and back again. – Jeremy Gooch Nov 11 '13 at 09:49