Apache in addition to being used as a web server for static or dynamic content, has other features developed for it (like most HTTP servers). Here we explain what a reverse proxy is and how to implement it, also called a gateway server. This option allows resources to be retrieved from the same server or another one transparently to the web client, serving other static and/or dynamic content.
How does a reverse proxy work?
In this scenario, the service itself does not generate content or host data; instead, the content is obtained from Backend servers, which normally have a direct connection to internal networks. When the web service receives a request from a client, a request is made to one of these Backend servers, which handles it and generates the content. It then sends the content to the proxy server (Apache in this case), which sends the response to the client.
There are multiple reasons for implementing this feature, including security, high availability, load balancing, and centralized authorization. Normally, in these implementations, the architecture and infrastructure design of the Backend servers are isolated/protected from the outside (DMZ); the only connection should be to the proxy server (which receives and provides the response to the client).
Which protocols does Apache Proxy support?
Apache supports the most popular protocols, as well as several different load balancing algorithms (third-party modules can add support for additional protocols), and the set of modules must be loaded to provide the necessary features. These modules can be included statically at compile time or dynamically through their directive.
The set must include:
- mod_proxy, which provides basic proxy capabilities
- mod_proxy_balancer, or additional balancer modules if load balancing is required.
- One or more supported proxy protocol modules:
- AJP13 (Apache JServe protocol version 1.3): mod_proxy_ajp
- CONNECT (for SSL): mod_proxy_connect
- FastCGI: mod_proxy_fcgi
- FTP: mod_proxy_ftp
- HTTP/0.9, HTTP/1.0, and HTTP/1.1: mod_proxy_http
- HTTP/2.0: mod_proxy_http2
- SCGI: mod_proxy_scgi
- UWSGI: mod_proxy_uwsgi
- WS and WSS (Web-sockets): mod_proxy_wstunnel
Proxying with Apache
If you do not have Apache installed, you will need to install the package:
Debian/Ubuntu:
# apt install apache2RHEL/CentOS:
# yum install httpdThen enable the required modules; for this example, they are proxy, proxy_http, proxy_balancer, ssl, headers and the bybusyness method for balancing:
# a2enmod proxy proxy_http proxy_balancer headers ssl proxy_ajp lbmethod_bybusynessHowever, you could enable only the ones you need. Using the appropriate one will give you better performance when proxying with its advanced options. You can review the environment variables at each module's link on its official page (linked above).
To disable a module, for example proxy_ajp, use the following command:
# a2dismod proxy_ajpOnce the modules have been enabled, you need to restart the Apache service:
# systemctl restart apache2Then edit the site configuration:
# vi /etc/apache2/sites-available/000-default.confFor a simple proxy, this would be an example virtualhost configuration for the HTTP port. You can also set connection timeouts and/or add headers to the proxy (restart the service afterward):
<VirtualHost *:80>
ServerName dominio.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
ProxyPreserveHost On
ProxyAddHeaders On
ProxyPass / http://127.0.0.1:8080/ connectiontimeout=5 timeout=30
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>Here, proxying to the same server has been used, but it could be another server with a certificate configured, and you could also use a certificate on the proxy server, as in the following example where we used Certbot for the certificate (restart the service afterward):
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName dominioproxy.com
SSLCertificateFile /etc/letsencrypt/live/domainproxy.com-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domainproxy.com-0001/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
ProxyPreserveHost On
SSLProxyEngine On
ProxyPass / https://serverbackend.com
ProxyPassReverse / https://serverbackend.com
</VirtualHost>
</IfModule>For this example, an HTTPS connection to the backend server will also require that server to have a valid certificate. Otherwise, you will need to add the following to disable the checks:
SSLProxyVerify None
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off
SSLProxyCheckPeerExpire Off
Load balancing with Apache
There is also a proxy module that offers load balancing (proxy_balancer), which we enabled earlier in the article.
The following is an example configuration with cookie routing (restart the service afterward):
<IfModule mod_ssl.c>
<VirtualHost *:443>
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
ServerName dominioproxy.com
SSLCertificateFile /etc/letsencrypt/live/domainproxy.com-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domainproxy.com-0001/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Proxy "balancer://micluster">
BalancerMember "http://10.20.10.5:80"
BalancerMember "http://10.20.10.6:80"
ProxySet lbmethod=bybusyness
ProxySet stickysession=ROUTEID
</Proxy>
ProxyPass "/" "balancer://micluster"
ProxyPassReverse "/" "balancer://micluster"
</VirtualHost>
</IfModule>As you can see, we have used the bybusyness method. It tracks how many requests each worker currently has assigned, and a new request is automatically assigned to the cluster member with the fewest active requests. However, the following methods are available:
You will need to enable them before using them.
We hope this tutorial has been helpful. If you have questions about this or any other issue related to your servers on Clouding, do not hesitate to contact soporte@clouding.io We are here to help!