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.
- mod_proxy_balancer - To load balance requests to two or more target systems
- mod_lbmethod_bybusyness - Load Balancing based on pending requests
- mod_lbmethod_byrequests - Load Balancing based on the number of requests
- mod_lbmethod_bytraffic - Load Balancing based on the volume of traffic
- mod_lbmethod_heartbeat - Load Balancing based on heartbeat traffic count
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>
~]# <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 