Skip to main content

This post came about from one of those “I’ve always had someone else do this for me, so I never really knew what the hell I was talking about” situations.

For the last 10 years, someone else (web team, infrastructure team, etc) has always setup and configured reverse proxies for me as needed. Recently I was told, “You’re that team”. So I figured, what the hell, no biggie.

Turns out, there was one little hangup what I was going crazy over, but I finally figured it out. This solution is probably for beginners, but sometimes the simplest of things trips up the rockstars out there =)

So, why use a revers proxy for OAM? You don’t want your app servers in the DMZ (public / internet facing) because people will break into them. So you put a reverse proxy in the DMZ and keep all your app servers safe in the intranet. Now there’s not direct access to the app servers from evil outsiders. Another reason to do this is for efficiency. If you have 100 applications to protect, you would have to install / config / test 100 different webgates. Lame. With a reverse proxy, you setup one, and it filters all requests for all apps (funnel effect). Obviously with all your traffic for all apps going to a 1 reverse proxy, you’ll need some load balances and multiple boxes. Blah blah blah.

How do you setup a reverse proxy? Well, if you have an OHS / Apache web server and your application that you’re protecting is on WebLogic, Oracle has a mod plugin for you that works great and is easy peasy. But what if you need to reverse proxy an IIS server (like my case). Now we get to the “I learned something new today” part.

Here’s the gist:

The servers I needed to proxy were app1.domain.com, and app2.domain.com

With all the Apache proxy docs out there they tell you to do this:

ProxyPass /foo/ http://app1.domain.com/foo/
ProxyPassReverse /foo/ http://app1.domain.com/foo/
ProxyPass /bar/ http://app1.domain.com/bar/
ProxyPassReverse /bar/ http://app2.domain.com/bar/

This will then show all app1 pages here: http://revprox.domain.com/foo/
And all app2 pages here: http://revprox.domain.com/bar/

And it works great!

Problem… my servers application root context is / on both servers and the directory structure after the app server domain and in my proxy need to match (/foo/ http://app1.domain.com/foo/) If they don’t, you get awesome behavior where you get redirected or linked out of the proxy (ie, it fails). In essence, I wanted to do this:

ProxyPass /foo/ http://app1.domain.com/

Don’t get me wrong, that will work, but for only one application. My problem is that I have two apps that are both “/”.

So here’s what I did. First, in the httpd.conf file, uncomment “Include conf/extra/httpd-vhosts.conf”. Then add this chunck at the bottom:

ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>

Save and close your file.

Now open up the ./extras/httpd-vhosts.conf file.

Wipe out everything in there because their examples don’t actually work. You’ll get Forbidden 403 errors up the butt. Put this in there:

NameVirtualHost *:8080<VirtualHost *:8080>
ServerAdmin [email protected]
DocumentRoot /usr/local/apache2RP/vhosts/app1/html
ServerName app1.revprox.domain.com
<directory /usr/local/apache2RP/vhosts/app1/html>
allow from all
</directory>
ProxyPass / http://app1.domain.com:80/
ProxyPassReverse / http://app1.domain.com:80/
</VirtualHost>
<VirtualHost *:8080>
ServerAdmin [email protected]
DocumentRoot /usr/local/apache2RP/vhosts/app2/html
ServerName app2.revprox.domain.com
<directory /usr/local/apache2RP/vhosts/app2/html>
allow from all
</directory>
ProxyPass / http://app2.domain.com:80/
ProxyPassReverse / http://app2.domain.com:80/
</VirtualHost>

Save, close, and bounce Apache.

BAM! You’re done. =)

I’ll break it down for ya:

NameVirtualHost *:8080 < This is the part that says what IP and ports to listen to. * = all IP addresses and my reverse proxy is running on 8080.

<VirtualHost *:8080> < Start tag for a new virtual host. The *:8080 works the same as the NameVirtualHost part.

ServerAdmin [email protected] < lame crap that you put dummy info in

DocumentRoot /usr/local/apache2RP/vhosts/app2/html < The physical path to where all files for this virtual host will be served from. THIS PATH MUST EXIST! I know we’re not loading anything from here, but it’s gotta be there, so just make it.

<directory /usr/local/apache2RP/vhosts/app2/html>allow from all</directory> < This part is super important and Apache leaves it out of their “examples”. This lets the pages actually be served =)

ProxyPass / http://app1.domain.com:80/ < This says to forward all requests to root “/” to http://app1.domain.com:80/ (Make sure you have the trailing slash).

ProxyPassReverse / http://app1.domain.com:80/ < This says to return all requests from the server to http://app1.domain.com:80/ (remember the / again). So when the server issues a 302 redirect or other things, it’ll send them through the proxy URL.

</VirtualHost> < This ends the block for this virtual host.

So in the end, we’re able to Reverse Proxy all root requests for every app server by using virtual hosts =). Also, we only need to install 1 webgate on this proxy server to intercept all requests. Booyah!

Last thing, in case it’s not obvious, you need to make sure that app1.revprox.domain.com is in the DNS otherwise none of this will work. To test it out without access to the DNS servers, just edit your HOSTS file and point the IP to the reverse proxy server. That’ll do the trick. Oh! And if you make a request to a non-existent virtual host (or even the regular web root), the web server will now default to sending all unmatched traffic to the FIRST Virtual Host setup. More solutions around this can be used with the ServerAlias tag in each Virtual Host grouping.

I’m out.