Tomcat

Apache Tomcat Reverse Proxy Configuration Tutorial

In computer networks, a reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client as if they originated from the proxy server itself. A reverse proxy acts as an intermediary for its associated servers to be contacted by any client.
 
 
 
 
  
 
 

 
Quite often, popular web servers utilize reverse proxy functionality, acting as shields for application frameworks with weaker HTTP capabilities.

1. The tools

  • Java JDK
  • Apache Tomcat
  • Apache httpd server
  • mod_jk connector

2. Introduction

The Apache HTTP Server module mod_jk and its ISAPI and NSAPI redirector variants for Microsoft IIS and the iPlanet Web Server connect the web server to a Tomcat backend using the AJP protocol. The web server receives an HTTP/HTTPS request and the module forwards the request to Tomcat. This function is usually called a gateway or a proxy, in the context of HTTP it is called a reverse proxy.

3. Prerequisites

  • JDK installed

4. Download Tomcat

Go to the page https://tomcat.apache.org/download-80.cgi and download the tomcat server as a zip compressed file for windows.

1 Download Tomcat for Windows
1 Download Tomcat for Windows

5. Download Apache httpd server

Go to the page http://www.apachehaus.com/cgi-bin/download.plx and download the httpd server as a zip compressed file for windows.
The Apache foundation doesn’t provide binaries for the httpd server. We are going to use a binary distribution from the recommended sites in the Apache web site.

2 download httpd server
2 download httpd server

6. Tomcat Installation

6.1 Uncompress Apache Tomcat

Choose an installation directory and uncompress the Tomcat server in its own directory.

4 Uncompress Tomcat
3 Uncompress Tomcat

6.2 Install the Tomcat service

Open the Windows terminal and go to the Tomcat Installation bin directory.

Tomcat installation directory

C:\Java\Apache Tomcat 8.0.15\bin>

Install the service with the following command:

Install Tomcat service

C:\Java\Apache Tomcat 8.0.15\bin>service install

You should get an output similar to this:

install Tomcat output

Installing the service 'Tomcat8' ...
Using CATALINA_HOME:    "C:\Java\Apache Tomcat 8.0.15"
Using CATALINA_BASE:    "C:\Java\Apache Tomcat 8.0.15"
Using JAVA_HOME:        "C:\Java\jdk1.8.0_40"
Using JRE_HOME:         "C:\Java\jre1.8.0_40"
Using JVM:              "C:\Java\jre1.8.0_40\bin\client\jvm.dll"
The service 'Tomcat8' has been installed.

6.3 Start the Tomcat service

Start the service with the following command:

Start tomcat output

C:\Java\Apache Tomcat 8.0.15\bin>sc start Tomcat8

You should get an output similar to the following:

console

SERVICE_NAME: Tomcat8
        TYPE               : 10  WIN32_OWN_PROCESS
        STATUS             : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_OUTPUT_CODE  : 0  (0x0)
        SERVICE_OUTPUT_CODE: 0  (0x0)
        CHECK-POINT        : 0x0
        START-INDICATOR    : 0x7d0
        PID                : 5552
        MARKS              :

6.4 Check that tomcat is running

Open the browser in the URL: http://localhost:8080 and you should see the Tomcat Welcome screen.

5 Tomcat Welcome
4 Tomcat Welcome

7. Apache httpd Installation

7.1 Uncompress Apache httpd server

Choose a directory and uncompress the Apache httpd server.

6 Uncompress Apache httpd server
5 Uncompress Apache httpd server

7.2 Edit the server root

Before we run the Apache httpd server we need to tell Apache where is the server root. Open the httpd server configuration file and edit the SRVROOT parameter using the appropriate directory.

SRVROOT

Define SRVROOT "C:\Java\Apache24"

7.3 Install the httpd service

Open the Windows terminal and go to the httpd server Installation bin directory.

httpd server bin installation directory

C:\Java\Apache24\bin>

Install the service with the following command:

Install httpd server service

C:\Java\Apache24\bin>httpd -k install

You should get an output similar to this:

install Tomcat output

Installing the 'Apache2.4' service
The 'Apache2.4' service is successfully installed.
Testing httpd.conf....
Errors reported here must be corrected before the service can be started.

7.4 Start the Apache service

Start the service with the following command:

Start Apache output

C:\Java\Apache24\bin>sc start Apache2.4

You should get an output similar to the following:

Apache Output

SERVICE_NAME: Apache2.4
        TYPE               : 10  WIN32_OWN_PROCESS
        STATUS             : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_OUTPUT_CODE  : 0  (0x0)
        SERVICE_OUTPUT_CODE: 0  (0x0)
        CHECK-POINT        : 0x0
        START-INDICATOR    : 0x7d0
        PID                : 3268
        MARKS              :

7.5 Check that Apache is running

Open the browser in the URL: localhost and you should see the httpd server Welcome screen.

7 Apache httpd server welcome screen
6 Apache httpd server welcome screen

8. Apache HTTPD Proxy Support

Apache HTTPD supports an optional module (mod_proxy) that configures the web server to act as a proxy server. This can be used to forward requests for a particular web application to a Tomcat instance, without having to configure a web connector such as mod_jk. To accomplish this, you need to perform the following tasks:

Configure your copy of Apache so that it includes the mod_proxy module. If you are building from source, the easiest way to do this is to include the –enable-module=proxy directive on the ./configure command line.
If not already added for you, make sure that you are loading the mod_proxy module at Apache startup time, by using the following directives in your httpd.conf file:

mod_proxy

LoadModule proxy_module  {path-to-modules}/mod_proxy.so
AddModule  mod_proxy.c

Include two directives in your httpd.conf file for each web application that you wish to forward to Tomcat. For example, to forward an application at context path /javacodegeeks:

ProxyPass

ProxyPass         /javacodegeeks  http://localhost:8080/app/javacodegeeks
ProxyPassReverse  /javacodegeeks  http://localhost:8080/app/javacodegeeks

which tells Apache to forward URLs of the form http://localhost/javacodegeeks/* to the Tomcat connector listening on port 8080. Configure your copy of Tomcat to include a special Connector element, with appropriate proxy settings, for example:

Connector

<Connector port="8081" ...
           proxyName="www.mycompany.com"
           proxyPort="80"/>

which will cause servlets inside this web application to think that all proxied requests were directed to www.javacodegeeks.com on port 80.
It is legal to omit the proxyName attribute from the Connector element. If you do so, the value returned by request.getServerName() will by the host name on which Tomcat is running. In the example above, it would be localhost If you also have a Connector listening on port 8080, the requests to either port will share the same set of virtual hosts and web applications.
 
You might wish to use the IP filtering features of your operating system to restrict connections to port 8080 (in this example) to be allowed only from the server that is running Apache. When requests are proxied by Apache, the web server will be recording these requests in its access log. Therefore, you will generally want to disable any access logging performed by Tomcat itself.

When requests are proxied in this manner, all requests for the configured web applications will be processed by Tomcat including requests for static content. You can improve performance by using the mod_jk web connector instead of mod_proxy. mod_jk can be configured so that the web server serves static content that is not processed by filters or security constraints defined within the web application’s deployment descriptor (/WEB-INF/web.xml).

At this point the Apache httpd server its working as a reverse proxy front end of the Tomcat instance.

9. Typical Problems

A reverse proxy is not totally transparent to the application on the backend. For instance the host name and port the original client needs to talk to belong to the web server and not to the backend, so the reverse proxy talks to a different host name and port. When the application on the backend returns content including self-referential URLs using its own backend address and port, the client will usually not be able to use these URLs.
 
Another example is the client IP address, which for the web server is the source IP of the incoming connection, whereas for the backend the connection always comes from the web server. This can be a problem, when the client IP is used by the backend application.

10. AJP as a Solution

Most of these problems are automatically handled by the AJP protocol and the AJP connectors of the backend. The AJP protocol transports this communication metadata and the backend connector presents this metadata whenever the application asks for it using Servlet API methods.

The Apache JServ Protocol (AJP) is a binary protocol that can proxy inbound requests from a web server through to an application server that sits behind the web server.

It also supports some monitoring in that the web server can ping the application server. Web implementors typically use AJP in a load-balanced deployment where one or more front-end web servers feed requests into one or more application servers. Sessions are redirected to the correct application server using a routing mechanism wherein each application server instance gets a name (called a route). In this scenario the web server functions as a reverse proxy for the application server.

AJP runs in Apache HTTP Server using the mod_jk plugin and in Apache using the provided Proxy AJP, mod_proxy and proxy balancer modules together.

In some situations this is not enough though. Assume there is another less clever reverse proxy in front of your web server, for instance an HTTP load balancer or similar device which also serves as an SSL accelerator.

Then you are sure that all your clients use HTTPS, but your web server doesn’t know about that. All it can see is requests coming from the accelerator using plain HTTP.

Another example would be a simple reverse proxy in front of your web server, so that the client IP address that your web server sees is always the IP address of this reverse proxy, and not of the original client. Often such reverse proxies generate an additional HTTP header, like X-Forwareded-for which contains the original client IP address or a list of IP addresses, if there are more cascading reverse proxies in front. It would be nice, if we could use the content of such a header as the client IP address to pass to the backend.

So we might need to manipulate some of the data that AJP sends to the backend. When using mod_jk inside the Apache HTTP Server you can use several Apache environment variables to let mod_jk know, which data it should forward. These environment variables can be set by the configuration directives SetEnv or SetEnvIf, but also in a very flexible way using mod_rewrite.

11. URL Handling

11.1 URL Rewriting

You need to include the rewrite valve class org.apache.catalina.valves.rewrite.RewriteValve in your application’s context. This can be in the global context.xml or in the context block of a host in the server.xml. Create a rewrite.config file containing your rewrites into your application WEB-INF folder.

11.1.1 Configure valve in Tomcat context.xml

Using the global context.xml will affect all virtual host.

RewriteValve Context

<?xml version='1.0' encoding='utf-8'?>
<!-- The contents of this file will be loaded for each web application -->
<Context>
    <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
</Context>

11.1.2 Configure valve on an individual host

If we want to set up the valve rewrite rule only on an individual host, we need to edit the server.xml and add the RewriteValve class to the virtual host.

RewriteValve Virtual Host

<Host name="JavaCodeGeeks.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
  <Context path="" docBase="C:/devel/java/www">
    <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
  </Context>
</Host>

11.1.3 Rewrite rules

As we say earlier rewrite valve is similar to Apache HTTPD mod_rewrite so we can use similar regular expression rules to make the rewrite work.

If you are using a global rewrite to effect all virtual hosts, then we can drop your rewrite.config into the WEB-INF. For individual virtual hosts, We will need to locate the WEB-INF of our application.

We are going to create a rewrite rule to make our url’s pretty

so for example:

Original URL

http://localhost:8080/w/index.jsp?title=javacodegeeks

Are rewritten to

Rewritten URL

http://localhost:8080/app/javacodegeeks

Our rule is going to be:

 

RewriteRule   ^app/(.+)$   w/index.jsp?title=$1   [L]

Remember we can use this rule on our server context or on an individual virtual host.

Our public URL is going to be:

Proxy URL

 http://localhost/app/javacodegeeks

That is redirected to the inside Apache Tomcat using the ATTPD proxy and Tomcat rewrite to the original URL.

11.2 URL Encoding

Some types of problems are triggered by the use of encoded URLs. For the same location there exist a lot of different URLs which are equivalent. The reverse proxy needs to inspect the URL in order to apply its own authentication rules and to decide, to which backend it should send the request. Therefore the request URL first is normalized: percent encoded characters are decoded, /./ is replaced by /, /XXX/../ is replaced by / and similar manipulations of the URL are done.
 
After that, the web server might apply rewrite rules to further change the URL in less obvious ways. Finally there is no more way to put the resulting URL in an encoding, which is “similar” to the one which was used for the original URL.

12. Conclusion

A reverse proxy server is a type of proxy server that typically sits behind the firewall in a private network and directs client requests to the appropriate backend server.
A reverse proxy provides an additional level of abstraction and control to ensure the smooth flow of network traffic between clients and servers.

Common uses for a reverse proxy server include:

Load balancing: A reverse proxy server can act as a traffic supervisor, sitting in front of your backend servers and distributing client requests across a group of servers in a manner that maximizes speed and capacity utilization while ensuring no one server is overloaded, which can degrade performance. If a server goes down, the load balancer redirects traffic to the remaining online servers.

Web acceleration: Reverse proxies can compress inbound and outbound data, as well as cache commonly requested content, both of which speed up the flow of traffic between clients and servers. They can also perform additional tasks such as SSL encryption to take load off of your web servers, thereby boosting their performance.

Security and anonymity: By intercepting requests headed for your backend servers, a reverse proxy server protects their identities and acts as an additional defense against security attacks. It also ensures that multiple servers can be accessed from a single record locator or URL regardless of the structure of your local area network.

Jesus Boadas

I'm a self taught programmer, I began programming back in 1991 using an IBM A10 mainframe with Pascal an Assembler IBM 360/70 emulator and Turbo C on a X86 PC, since that I work for the banking industry with emerging technologies like Fox Pro, Visual Fox Pro, Visual Basic, Visual C++, Borland C++, lately I moved out to the Airline industry, leading designing and programming in-house web applications with Flex, Actionscript, PHP, Python and Rails and in the last 7 years I focused all my work in Java, working on Linux servers using GlassFish, TomCat, Apache and MySql.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Joel
Joel
6 years ago

Hi Jesus,

I have been working in Java Web services for about two years and I would to consolidate my operational knowledge with concept knowledge. This article is amazing, but what book should I read to go deep in this matter?

Back to top button