Arcticles

by Michael Hampicke

Exchange Server

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

Please calculate 7 plus 6.