Bootstrap FreeKB - Apache (Web Server) - Load Balance Proxy Pass
Apache (Web Server) - Load Balance Proxy Pass

Updated:   |  Apache (Web Server) articles

An Apache HTTP web server can be configured with proxy modules which will allow the HTTP web server to be a forward or reverse proxy. For example, a request coming into the web server could be forwarded onto www.example.com, and then www.example.com would return it's response through the proxy to the client.

flowchart LR
A["Client"]
C["http://www.example.com"]
B["Forward Proxy"]
A --request--> B --request--> C
C --response--> B --response--> A

 

The Apache HTTP web server will need to load the mod_proxy module which means placing the mod_proxy.so file in the "modules" directory of the web server, such as /opt/webserver/modules/mod_proxy.so.

Additionally, mod_proxy_http and/or mod_proxy_ftp are needed to proxy HTTP and FTP requests.

  • mod_proxy_http - To proxy HTTP requests
  • mod_proxy_ftp - To proxy FTP requests

Additionally, if the web server will be load balancing requests, then the mod_proxy_balancer module will also need to be placed in the "modules" directory of the web server and one or more of the mod_lbmethod_by modules must also be placed in the "modules" directory of the web server as at least one of these modules is required for load balancing scheduling.

You may need to install Apache with the --enable-proxy and --enable-proxy-balancer flags to get the latest stable mod_proxy and mod_lbmethod modules. Check out my article on Installing Apache on Linux.

A basic forward proxy

In this example, the request will simply go through the proxy and be forwarded on.

LoadModule proxy_module                modules/mod_proxy.so
LoadModule proxy_http_module           modules/mod_proxy_http.so
LoadModule proxy_balancer_module       modules/mod_proxy_balancer.so

<VirtualHost *:80>
   ServerName proxy.acme.com
   DocumentRoot "/var/www/site1"
 
   <Proxy *>
     AddDefaultCharset Off
     Order deny,allow
     Allow from all
   </Proxy>

</VirtualHost>

 

For example, a Python script could request http://www.example.com without going through a proxy.

#!/usr/bin/python
import requests

response = requests.get("http://www.example.com")
print(response.text)

 

Which would be something like this.

flowchart LR
A["Python script"]
B["http://example.com"]
A --request--> B
B --response--> A

 

And here is an example of the Python script submitting the GET request for http://example.com going through the forward proxy proxy.acme.com.

#!/usr/bin/python
import requests

response = requests.get("http://www.example.com", proxies={"http": "http://proxy.acme.com:80", "https": "https://proxy.acme.com:443" })
print(response.text)

 

Which would be something like this.

flowchart LR
A["Python script"]
B["acme.proxy.com"]
C["http://www.example.com"]
A --request--> B --request--> C
C --response--> B --response--> A

 

 

LDAP and Active Directory

Let's say you have a group in Active Directory named my_group and you have a few users that are members of the group, perhaps John Doe and Jane Doe. The mod_ldap and mod_authnz_ldap modules can be used so that only members of my_group are allowed to submit requests through the forward proxy. 

LoadModule proxy_module                modules/mod_proxy.so
LoadModule proxy_http_module           modules/mod_proxy_http.so
LoadModule proxy_balancer_module       modules/mod_proxy_balancer.so
LoadModule ldap_module                 modules/mod_ldap.so
LoadModule authnz_ldap_module          modules/mod_authnz_ldap.so

<VirtualHost *:80>
   ServerName proxy.acme.com
   DocumentRoot "/var/www/site1"
 
   <Proxy *>
     AuthType Basic
     AuthName "LDAP Authentication"
     AuthBasicProvider ldap
     AuthLDAPURL "ldap://ldap.acme.com:389/?uid"
     AuthLDAPBindDN "cn=serviceAccount,o=acme"
     AuthLDAPBindPassword "itsasecret"
     AuthLDAPGroupAttributeIsDN on
     AuthLDAPGroupAttribute member
     Require ldap-group cn=my_group,ou=Groups,o=acme
   </Proxy>

</VirtualHost>

 

In this scenario, I would also set LogLevel to debug at first, so you can run a few test cases to ensure LDAP is working.

LogLevel debug

 

Let's say Python is again used to submit a request through the proxy onto http://www.example.com. Notice in this example that no username or password was included in the request.

#!/usr/bin/python
import requests

response = requests.get("http://www.example.com", proxies={"http": "http://proxy.acme.com:80", "https": "https://proxy.acme.com:443" })
print(response.text)

 

In this scenario, the Apache error log should have something like this.

[Mon Mar 09 13:14:26.641434 2026] [authz_core:debug] [pid 350989:tid 123456789012480] mod_authz_core.c(818): [client 10.11.12.13:58594] AH01626: authorization result of Require ldap-group cn=my_group,ou=Groups,o=acme: denied (no authenticated user yet)
[Mon Mar 09 13:14:26.641438 2026] [authz_core:debug] [pid 350989:tid 123456789012480] mod_authz_core.c(818): [client 10.11.12.13:58594] AH01626: authorization result of <RequireAny>: denied (no authenticated user yet)

 

Let's attempt to authenticate with a user that is a member of my_group in Active Directory.

#!/usr/bin/python
import requests

password = input("password: ")

http_proxy_url = f"http://john.doe:{password}@proxy.acme.com:80"
https_proxy_url = f"https://john.doe:{password}@proxy.acme.com:80"

proxies = {
    "http": http_proxy_url,
    "https": https_proxy_url,
}

response = requests.get("http://www.example.com", proxies=proxies)
print(f"response.text = {response.text}")

 

In this scenario, the Apache log should have something like this, "granted".

[Mon Mar 09 13:17:43.991779 2026] [authz_core:debug] 
[pid 350988:tid 139626381043264] mod_authz_core.c(818): 
[client 10.11.12.13:40342] 
AH01626: authorization result of Require ldap-group cn=my_group,ou=Groups,o=acme: granted

 

Or "denied".

[Tue Mar 10 06:21:11.336816 2026] [authz_core:debug] 
[pid 594968:tid 139870957200960] mod_authz_core.c(818): 
[client 10.11.12.13:1853] 
AH01626: authorization result of Require ldap-group cn=my_group,ou=Groups,o=acme: 
denied (no authenticated user yet)

 

Proxy Pass

Here is an example of a web server configuration file (e.g. httpd.conf) with the proxy configurations. In this example, the second field of the ProxyPass line is /sample. This means that when http://<web server hostname or IP address>/sample is requested, the web server will proxy the request onto http://www.example.com:8080/sample. 

LoadModule proxy_module                modules/mod_proxy.so
LoadModule proxy_http_module           modules/mod_proxy_http.so
LoadModule proxy_balancer_module       modules/mod_proxy_balancer.so
LoadModule lbmethod_bybusyness_module  modules/mod_lbmethod_bybusyness.so
LoadModule lbmethod_byrequests_module  modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module   modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_byheartbeat_module modules/mod_lbmethod_byheartbeat.so

<VirtualHost *:80>
   ServerName www.example.com
   DocumentRoot "/var/www/site1"
 
   <Proxy *>
     AddDefaultCharset Off
     Order deny,allow
     Allow from all
   </Proxy>
 
   ProxyPass /sample http://www.example.com:8080/sample
   ProxyPassReverse /sample http://www.example.com:8080/sample

</VirtualHost>

 

The apachectl command can be used to determine if the modules have been successfully loaded into the web server.

~]# <web_server_root>/bin/apachectl -M
Loaded Modules:
  proxy_module (shared)
  proxy_http_module (shared)
  proxy_balancer_module (shared)
  lbmethod_bybusyness_module (shared)
  lbmethod_byrequests_module (shared)
  lbmethod_bytraffic_module (shared)
  lbmethod_byheartbeat_module (shared)

 

If, for example, www.example.com/sample is supposed to return a Tomcat app, if you get the Tomcat app, then the proxy is working.

 

Optionally, the AllowCONNECT directive can be used to define the ports that are allowed.

AllowCONNECT 80
<VirtualHost *:80>
   ServerName www.example.com
   DocumentRoot "/var/www/site1"
 
   <Proxy *>
     AddDefaultCharset Off
     Order deny,allow
     Allow from all
   </Proxy>
 
   ProxyPass /sample http://www.example.com:8080/sample
   ProxyPassReverse /sample http://www.example.com:8080/sample

</VirtualHost>

 

Another advantage of using a proxy pass is being able to route requests to a number of different backends. For example, let's say you have different backend services listening on their own port.

http://www.example.com:8080/
http://www.example.com:8081/
http://www.example.com:8082/

 

A single web server can proxy requests to each backend service.

ProxyPass /service1 http://www.example.com:8080/
ProxyPass /service2 http://www.example.com:8081/
ProxyPass /service3 http://www.example.com:8082/

 

A proxy pass can also route requests to different backend systems.

ProxyPass /backend1 http://www.server1.com:8080/
ProxyPass /backend2 http://www.server2.com:8080/
ProxyPass /backend3 http://www.server3.com:8080/

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 7930bc in the box below so that we can be sure you are a human.