Share this page:

Setting up a reverse proxy on Ubuntu 14.04 LTS with Apache 2.4

Apache can be configured as a proxy to redirect HTTP traffic to other servers.  When Apache is configured as a reverse proxy, it receives HTTP requests from the internet, and forwards them to another server to process the request.  This server, often referred to as a backend server or a worker node, sends a response through the proxy back to the client.  

Proxies often have more than one network interface.  One network interface receives HTTP requests from clients, and the other network interface forwards HTTP requests to servers on a different subnet.  Proxies act a bit like TCP/IP routers, but they don't forward all traffic, just HTTP requests and responses.  The interface that receives incoming HTTP requests can be considered the public interface, while the interface on the same subnet as the servers is a private interface.  This means the backend servers that handle web traffic can be kept on a seperate subnet from the rest of the network.

A reverse proxy is often used as a gateway to a collection of servers.  They can direct traffic for different sites to different servers.  This is useful if there are several servers, and each one hosts a different web site.  It means that several sites to be hosted from a single IP address.  In this case, the domain names for several different sites would point to the proxies public interface, and the proxy forwards traffic to different servers based on the host name in HTTP requests. Alternatively, a reverse proxy can spread the load across a collection of identical servers.  

This is useful in situations where more than one server is required to handle the traffic for one site.  In this example I'm going to set up a reverse proxy to a cluster of servers that all host the same site.  

Setting up the network interfaces

The proxy needs to have at least two network interfaces, and they should both be on different subnets.  You can access the network settings by clicking on the networking icon in the top left corner of the screen, and selecting 'Edit Connections...' from the drop down menu.

Networking drop down menu

In the network connections dialogue, select 'Wired connection 1' and click on the edit button:

Ubuntu Network Connections dialogue

This will bring up a dialogue for the public network interface.  Click on the IPv4 settings tab, and in the method tab, select manual.  Enter an IP address, netmask and gateway:

IP settings for wired connection 1

Save the settings, and then edit the settings for the second network interface: 

IP settings for wired connection 2

Note that the public interface has an IP address on subnet 192.168.0, and the private interface has an address on subnet 192.168.1.  Apache will listen for requests on the public interface, and forward them to backend servers through the private interface.

Install and configure Apache

Make sure Ubuntu is up to date, and then install Apache:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install apache2 -y

Install some Apache modules:

sudo a2enmod proxy proxy_http proxy_balancer

Check which version of Apache was installed:

apache2 -v
Server version: Apache/2.4.7 (Ubuntu)
Server built: Jul 22 2014 14:36:38

This step isn't necessary with Apache 2.2, but with Apache 2.4, fewer modules are enabled by default, so you will also need to enable these modules:

sudo a2enmod lbmethod_byrequests slotmem_shm

Setting up a virtual host

The virtual host file that's used to configure Apache must contain directives that tell Apache how many servers there are in the cluster of worker nodes, and what traffic to forward to those nodes. I'm going to use the default virtual host file, 000-default.conf, to store these directives. (Note that if you're working with Apache 2.2, the default virtual host file is called default.conf.) Use this command to open the file in gedit:

sudo gedit /etc/apache2/sites-available/000-default.conf

Suppose the reverse proxy needs to forward traffic for a site named example.com to a cluster of servers.  The ServerName directive is used to make this virtual host handle traffic for any request with example.com in the host name.  The ServerAlias directive is set up to ensure that this virtual host also handles traffic for subdomains of example.com.

ServerName  example.com
ServerAlias *.example.com

It's best to turn off proxy requests for security reasons.  Otherwise people could use your server as a proxy to hide behind while they engage in illegal activity. It's also a good idea to make sure the host name is preserved when the reverse proxy forwards HTTP requests.  You can acheive these things by adding the following two lines to the virtual host:

ProxyRequests Off
ProxyPreserveHost On

In this example I'm going to assume that there are two servers in the cluster with identical web sites on each of them, and with IP addresses 192.168.1.13 and 192.168.1.14. The virtual host file must contain a definition of the cluster that will handle traffic for this site:

    <Proxy balancer://my_cluster>
        BalancerMember http://192.168.1.13:80
        BalancerMember http://192.168.1.14:80

        AllowOverride None
        Order allow,deny
        allow from all

        ProxySet lbmethod=byrequests
    </Proxy>

This defines a cluster called my_cluster with two worker nodes.  The ProxySet directive is used to tell the load balancer to distribute requests in a round-robin manner. Requests can also be ditrbuted based on the amount of traffic that each backend server has sent:

ProxySet lbmethod=bytraffic

or by the number of pending requests on each backend server:

ProxySet lbmethod=bybusyness

The ProxyPass directive is used to send traffic matching a particular URL to the cluster.  In this case all traffic needs to be forwarded to my_cluster:

ProxyPass / balancer://my_cluster/

The complete virtual host file should look something like this:

<VirtualHost *:80>
    ServerName  example.com
    ServerAlias *.example.com

    ProxyRequests Off
    ProxyPreserveHost On

    <Proxy balancer://my_cluster>
        BalancerMember http://192.168.1.13:80
        BalancerMember http://192.168.1.14:80

        AllowOverride None
        Order allow,deny
        allow from all

        ProxySet lbmethod=byrequests
    </Proxy>

    ProxyPass / balancer://my_cluster/

    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Save the file and restart Apache:

sudo service apache2 restart

On a PC on the local network, open a browser and visit the IP address of the load balancer's public interface.  The request will be passed through the reverse proxy to one of the backend servers which will handle the request and send a response back through the proxy. The web site on the backend server should be visible in your browser.  Try modifiying a page on one of the servers. If you view the modified page and hit Shift-F5 to force the browser to refresh, the modified page will be displayed about 50% of the time.

If you have problems getting this to work, check Apache's logs on the load balancer (access.log and error.log in /var/log/apache2/), and also check the web server logs on the backend servers.


Comments