Using the Apache HTTP Server (mod_proxy) as a reverse proxy to a WebLogic Server

Peter Lorenzen
23/04-2013

If you are using a WebLogic Cluster you need a proxy in front of the cluster to provide load balancing. You need either a hardware load balancer or a Web Server with the Oracle Web server plug-in.

Even if you are not using a Cluster it makes sense to place a proxy in front of your WebLogic server to provide an extra layer of security. You can use the Apache HTTP Server with the mod_proxy module to configure a reverse proxy.

You can of cause also use the Oracle Web server plug-in but it is a proprietary module that you have to manually download and install. mod_proxy is open source and since I mostly work with Red Hat servers it is available in the standard Red Hat channel. Red Hat provide security updates so “all” you have to do is run yum update once in a while to get the latest updates. If you use the Oracle Web server plug-in you have to manually check for updates.

I often you use a solution where an Apache HTTP Server is placed in a DMZ network segment. SSL is terminated at the Apache server and mod_proxy is used to proxy requests to an WebLogic Server in the production network segment.

In this example we have an Internet domain called theheat.dk. The public IP 217.116.232.220 is NATed to 10.10.10.1 on winterfell.

Apache has already been installed on winterfell, the mod_proxy module loaded, SSL configured and WebLogic is running on wintermute.

In your VirtualHost in the ssl.conf (httpd-ssl.conf on Windows) file you can add something like this:

ProxyPass        / http://10.10.10.10:8001/
ProxyPassReverse / http://10.10.10.10:8001/

The ProxyPass and ProxyPassReverse directives are used to forward all requests to the WebLogic Server running on 10.10.10.10.

Another example:

ProxyPass        /service/ws1 http://10.10.10.10:8001/ws1_v101
ProxyPassReverse /service/ws1 http://10.10.10.10:8001/ws1_v101

ProxyPass        /service/ws2 http://10.10.10.10:8001/ws2_v300
ProxyPassReverse /service/ws2 http://10.10.10.10:8001/ws2_v300

Here only requests matching two specific paths are forwarded to two Web Services.

If you need more control over what is proxied you can use the ProxyPassMatch directive.

If you want to prevent a path from being proxied you can use the ! directive.

Configure the WebLogic Server to use a proxy

The above will proxy the requests to the WebLogic Server.

In some situations it will not work though. The WebLogic Server does not know that there is a proxy in front of it and sometimes it will return URLs to the end-user that contains the server name. In this example it will return URLs that contain wintermute. Since wintermute is not known on the Internet it will fail.

I have experienced this when an ADF application session timeout and asks the user to log in again. The URL returned to the user is wrong.

Another example is the WSDL for a Web Service. The location of the end-point and references to XML schemas will use the host name.

To remedy this you can configure WebLogic so I knows that there is a proxy in front of it. WebLogic will use this information and dynamically change the references, so they uses the proxy information.

First you must enable the WebLogic Plug-In. We are not using the WebLogic Plug-In but we still need to enable it here.

Domain Structure > Environment > Servers > managed01 > Configuration General > Advanced:

Next you must insert the proxy and port.

Domain Structure > Environment > Servers > managed01 > Protocols > HTTP:

The little yellow triangles with the exclamation mark tell us that we need to restart the WebLogic server for the changes to take effect.

But it will still not work. We have told WebLogic what the frontend HTTPS host and port is, but we have terminated SSL at the Apache proxy and uses HTTP between Apache and WebLogic.
We need to tell WebLogic that the proxy was originally called with HTTPS.

We do this by inserting an tag in the HTTP header in the Apache configuration:

RequestHeader set WL-Proxy-SSL true
ProxyPass        / http://10.10.10.10:8001/
ProxyPassReverse / http://10.10.10.10:8001/

Now everything should be working.

If you are using a cluster you should set Frontend Host and Frontend HTTPS Port for the cluster not the individual Managed Server. For more information:
http://goo.gl/k0jUe

ProxyPreserveHost

In some situations you need to access your application from both the Internet and from an internal network segment using the internal server names.

To accomplish this you need to change the Apache configuration:

ProxyPreserveHost On
RequestHeader set WL-Proxy-SSL true
ProxyPass        / http://10.10.10.10:8001/
ProxyPassReverse / http://10.10.10.10:8001/

Setting “ProxyPreserveHost On” will tell Apache to pass the host used in the request to the WebLogic Server.

You also need to remove the Frontend HTTPS Host from you WebLogic Server or Cluster.

Now I can access a Web Service via both:
https://theheat.dk/service/ws1?WSDL
And:
https://winterfell/service/ws1?WSDL

The WSDL will either contain reference to theheat.dk or winterfell depending of which URL I use to access the WSDL with.

{ 6 comments… read them below or add one }

Tagore October 17, 2013 at 08:33

Thanks Peter, your article really helps.

Rolf Amfelt January 7, 2014 at 07:29

Hej Peter
Can this method be used with webforms?
How to set sticky sessions? For each serc server behind the proxy.
/Rolf

Peter Lorenzen January 7, 2014 at 09:36

Hi Rolf,

Yes you can do this for Forms, but not for clusters. If you use WebLogic clustering you need the Apache HTTP Server Plug-In aka. mod_wl.
Regards Peter

Rolf Amfelt January 7, 2014 at 10:02

Hej Peter
Thanks for fast answer.
We do not use WebLogic clustering 4 singel WLS behinde a proxy And no ssl. Keep getting FRM-93618 when the form starts. -:( I must be missing somthing.

Roland June 7, 2014 at 00:28

Can you shared the file Apache configuration ?

Peter Lorenzen June 12, 2014 at 14:46

Hi,
You should not need more than the examples I have provided. What is it precise you need? Do you get any errors?
Regards Peter

Leave a Comment

Previous post:

Next post: