Arcticles
by Michael Hampicke
Apache Reverse Proxy as Load Balancer for Exchange DAG
“Poor Man’s” Load Balancing for an Exchange 2016 DAG with Apache httpd
When you run Exchange 2016 in a DAG but don’t want to introduce a full-blown load balancer, Apache httpd can give you a pragmatic reverse-proxy front end. This setup terminates TLS, forwards Exchange paths (OWA, MAPI, EWS, ActiveSync, Autodiscover), and implements a hot-standby “poor man’s” load balancing model: one active backend and one standby that takes over automatically if the primary drops.
What this config does (short & sweet)
- Reverse proxy for Exchange: Proxies /owa, /mapi, /ews, /oab, ActiveSync, and Autodiscover to your backend Exchange CAS roles.
- Hot-standby failover: Uses mod_proxy_balancer with status=+H on the second node so it only comes online if the primary fails.
- Frontend hygiene: TLS hardening, header cleanup (hide tech stack/versions), generous timeouts for Outlook clients, and Proxy100Continue Off to avoid Autodiscover quirks.
- Operational tools: Optional /balancer-manager (IP-restricted) to observe/adjust members.
- Compatibility tweaks: Removes specific ModSecurity rules for known noisy Exchange traffic patterns.
This won’t replace a real LB with health probes and per-service weighting, but it’s rock-solid for labs and small shops.
Notes
- Modules needed: proxy, proxy_http, proxy_balancer, lbmethod_bytraffic, ssl, headers, (optionally) proxy_wstunnel and ModSecurity if you use it.
- Certificates: Use a cert that covers both mail.example.tld and autodiscover.example.tld (wildcard or SAN).
- Health/failover: Apache’s balancer marks the standby with status=+H. If the primary is down (TCP/SSL errors), traffic fails over. You can also toggle members in /balancer-manager.
- Outlook client behavior: Large ProxyTimeout/TimeOut values help long-lived MAPI/ActiveSync sessions. Proxy100Continue Off prevents the “Autodiscover 100-Continue” oddities in some tests.
- Security: Header stripping reduces fingerprinting. Protocols/ciphers exclude SSLv2/3 and TLS 1.0/1.1.
ServerLimit 500
MaxRequestWorkers 500
MaxKeepAliveRequests 10000
# FrontEnd Server Settings
define FrontEndServerName mail.example.tld
define FrondEndServerAlias autodiscover.example.tld
define FrontEndServerAdmin admin@example.tld
# Exchange Server IPs
define BackEndServerIP 10.0.0.10
define BackEndServerIPStandby 10.0.0.11
# Hot-Standby Balancer
<Proxy "balancer://hotcluster">
BalancerMember "https://${BackEndServerIP}"
BalancerMember "https://${BackEndServerIPStandby}" status=+H retry=10
ProxySet lbmethod=bytraffic
</Proxy>
# Optional: balancer UI (restrict tightly)
<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 10.0.0.0/24
</Location>
# Only redirect http to https and some logging
<VirtualHost *:80>
ServerName ${FrontEndServerName}
ServerAlias ${FrondEndServerAlias}
ServerAdmin ${FrontEndServerAdmin}
ErrorLog /var/log/apache2/mail.example.tld-error.log
CustomLog /var/log/apache2/mail.example.tld-access.log combined
ProxyRequests Off
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>
# HTTPS Virtual Host for Exchange Server
<VirtualHost *:443>
ServerName ${FrontEndServerName}
ServerAlias ${FrondEndServerAlias}
ServerAdmin ${FrontEndServerAdmin}
ErrorLog /var/log/apache2/mail.example.tld-error.log
CustomLog /var/log/apache2/mail.example.tld-access.log combined
Header always set X-Frame-Options SAMEORIGIN
Header set Server Apache
Header unset X-AspNet-Version
Header unset X-OWA-Version
Header unset X-Powered-By
RequestHeader unset Expect early
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
ProxyTimeout 1800
RequestHeader edit Transfer-Encoding Chunked chunked early
RequestHeader unset Accept-Encoding
TimeOut 1800
# avoid auto discover errors in Microsoft Remote Connectivity Analyzer
# https://support.sophos.com/support/s/article/KB-000044067?language=en_US
Proxy100Continue Off
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
# OWA
ProxyPass /owa balancer://hotcluster/owa
ProxyPassReverse /owa balancer://hotcluster/owa
ProxyPass /OWA balancer://hotcluster/OWA
ProxyPassReverse /OWA balancer://hotcluster/OWA
<LocationMatch "/owa/*">
SecRuleRemoveById 949110 980130 941260 941250 941180 941160 941140 941100 921130 941190 941170 941130 920420 941310 932100 932105 934170 980170 932250 932230 932235 932260 932380 934170 942100
</LocationMatch>
# MAPI over HTTP
ProxyPass /mapi balancer://hotcluster/mapi
ProxyPassReverse /mapi balancer://hotcluster/mapi
<LocationMatch "/mapi/*">
SecRuleRemoveById 920420 949110 980130 200002 941120
</LocationMatch>
# EWS
ProxyPass /ews balancer://hotcluster/ews
ProxyPassReverse /ews balancer://hotcluster/ews
ProxyPass /EWS balancer://hotcluster/EWS
ProxyPassReverse /EWS balancer://hotcluster/EWS
<LocationMatch "/EWS/*">
SecRuleRemoveById 941100 949110 980130 941120 941130 200002 951110 959100 980140 951220 951120
</LocationMatch>
# OAB
ProxyPass /oab balancer://hotcluster/oab
ProxyPassReverse /oab balancer://hotcluster/oab
ProxyPass /OAB balancer://hotcluster/OAB
ProxyPassReverse /OAB balancer://hotcluster/OAB
ProxyPass /Oab balancer://hotcluster/Oab
ProxyPassReverse /Oab balancer://hotcluster/Oab
# ActiveSync
ProxyPass /Microsoft-Server-ActiveSync balancer://hotcluster/Microsoft-Server-ActiveSync
ProxyPassReverse /Microsoft-Server-ActiveSync balancer://hotcluster/Microsoft-Server-ActiveSync
<Location "/Microsoft-Server-ActiveSync">
SSLRenegBufferSize 31457280
</Location>
<LocationMatch "/Microsoft-Server-ActiveSync/*">
SecRuleRemoveById 949110 980130 920420 200002 980170
</LocationMatch>
# Autodiscover
ProxyPass /autodiscover balancer://hotcluster/autodiscover
ProxyPassReverse /autodiscover balancer://hotcluster/autodiscover
ProxyPass /Autodiscover balancer://hotcluster/Autodiscover
ProxyPassReverse /Autodiscover balancer://hotcluster/Autodiscover
ProxyPass /AutoDiscover balancer://hotcluster/AutoDiscover
ProxyPassReverse /AutoDiscover balancer://hotcluster/AutoDiscover
# Legacy access control (intentionally permissive for proxying)
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
# SSL Settings
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
SSLHonorCipherOrder off
# SSL Certificate (wildcard or SAN cert covering mail/autodiscover)
SSLCertificateFile /etc/ssl/wild.example.tld/wild.example.tld.crt
SSLCertificateKeyFile /etc/ssl/wild.example.tld/wild.example.tld.key
SSLCertificateChainFile /etc/ssl/wild.example.tld/root.crt
</VirtualHost>
We’ve been running this Apache reverse proxy setup in production for several years now without issues. On top of that, we also integrate ModSecurity with custom tuning to handle Exchange traffic more gracefully. The details of that configuration deserve their own write-up — an article for another day.
Comments
Comment by Jorge |
Hey there, I was wondering how to deal with Exchange Download Domains in regards to the apache reverse proxy.
Best,
Jorge
Add a comment