Many readers of this blog have requested an article on the subject of "Exchange Server and Reverse Proxy". Although there are already HowTos with Kemp, Sophos and F5, there also seems to be a need for open source solutions. Therefore, here is a HowTo for the use of Apache as a reverse proxy for Exchange Server.
In principle, the use of a reverse proxy in conjunction with Exchange servers is a good idea. In many small environments in particular, a simple NAT of ports 80 and 443 is often set up on the router to the Exchange server. However, this has the consequence that the Exchange Server with all its protocols, interfaces and services is published on the Internet. If neglected updates or zero-day exploits are added to this, it is only a matter of time before something bad happens to the Exchange Server.
A reverse proxy can provide some relief, as it is easier to control which Exchange services are published. For example, access to the Exchange Admin Center can be deactivated via reverse proxy. Some readers have also asked how only OWA can be made accessible from the Internet, but not all other protocols such as ActiveSync or MAPIoverHTTP.
Fun fact: Many automated attacks fail simply because a reverse proxy is present. HTTP header does not match "IIS", then on to the next target...
This article first deals with the installation and configuration of Apache as a reverse proxy for Exchange. In the next article, this configuration will be expanded a little.
Installing the operating system
I used Ubuntu Server 22.04 Minimal as the operating system. After the standard installation, I only carried out the network configuration and configured NTP for time synchronization.
Ubuntu Server can be downloaded here:
I run Ubuntu in a small VM with 2 vCPUs and 4GB RAM.
Install and activate the firewall
The UFW firewall can be installed and configured with the following commands. The configuration allows all outgoing connections; only HTTP, HTTPS and SSH are permitted for incoming connections:
apt-get install ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow http
ufw allow https
ufw enable
ufw status
Install Apache and activate modules
In order to use Apache as a reverse proxy for Exchange, Apache must first be installed and the necessary modules loaded:
apt-get install apache2
a2enmod headers
a2enmod rewrite
a2enmod proxy_http
a2enmod ssl
a2dismod mpm_event
a2enmod mpm_prefork
echo "ServerName 127.0.0.1" >> /etc/apache2/apache2.conf
systemctl restart apache2
Apache as reverse proxy for Exchange Server
Apache as reverse proxy
cd /etc/apache2/sites-available/
a2dissite 000-default.conf
touch 001-exchange-proxy.conf
a2ensite 001-exchange-proxy.conf
The proxy configuration for Exchange can now be added to the "001-exchange-proxy.conf" file:
#ServerLimit 300
#MaxRequestWorkers 300
MaxConnectionsPerChild 1
#FrontEnd Server Settings
#------------------------
define FrontEndServerName outlook.frankysweblab.de
define FrondEndServerAlias autodiscover.frankysweblab.de
define FrontEndServerAdmin webmaster@frankysweblab.de
#Exchange Server IP
#------------------------
define BackEndServerIP 192.168.100.112
#Only redirect http to https and some logging
ServerName ${FrontEndServerName}
ServerAlias ${FrondEndServerAlias}
ServerAdmin ${FrontEndServerAdmin}
#Logging
ErrorLog /var/log/apache2/exchange_80_error.log
CustomLog /var/log/apache2/exchange_80_access.log combined
ProxyRequests Off
#redirect http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
#HTTPS Virtual Host for Exchange Server
ServerName ${FrontEndServerName}
ServerAlias ${FrondEndServerAlias}
ServerAdmin ${FrontEndServerAdmin}
ErrorLog /var/log/apache2/exchange_443_error.log
CustomLog /var/log/apache2/exchange_443_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
RequestHeader edit Transfer-Encoding Chunked chunked early
RequestHeader unset Accept-Encoding
TimeOut 1800
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
Redirect / /owa/
#OWA
ProxyPass /owa https://${BackEndServerIP}/owa
ProxyPassReverse /owa https://${BackEndServerIP}/owa
ProxyPass /OWA https://${BackEndServerIP}/OWA
ProxyPassReverse /OWA https://${BackEndServerIP}/OWA
#MAPIoverHTTP
ProxyPass /mapi https://${BackEndServerIP}/mapi
ProxyPassReverse /mapi https://${BackEndServerIP}/mapi
#EWS
ProxyPass /ews https://${BackEndServerIP}/ews
ProxyPassReverse /ews https://${BackEndServerIP}/ews
ProxyPass /EWS https://${BackEndServerIP}/EWS
ProxyPassReverse /EWS https://${BackEndServerIP}/EWS
#OAB
ProxyPass /oab https://${BackEndServerIP}/oab
ProxyPassReverse /oab https://${BackEndServerIP}/oab
ProxyPass /OAB https://${BackEndServerIP}/OAB
ProxyPassReverse /OAB https://${BackEndServerIP}/OAB
#ActiveSync
ProxyPass /Microsoft-Server-ActiveSync https://${BackEndServerIP}/Microsoft-Server-ActiveSync connectiontimeout=900
ProxyPassReverse /Microsoft-Server-ActiveSync https://${BackEndServerIP}/Microsoft-Server-ActiveSync
SSLRenegBufferSize 31457280
#AutoDiscover
ProxyPass /autodiscover https://${BackEndServerIP}/autodiscover
ProxyPassReverse /autodiscover https://${BackEndServerIP}/autodiscover
ProxyPass /Autodiscover https://${BackEndServerIP}/Autodiscover
ProxyPassReverse /Autodiscover https://${BackEndServerIP}/Autodiscover
ProxyPass /AutoDiscover https://${BackEndServerIP}/AutoDiscover
ProxyPassReverse /AutoDiscover https://${BackEndServerIP}/AutoDiscover
AddDefaultCharset ISO-8859-1
Order deny,allow
Deny from all
Order deny,allow
Allow from all
#SSL Settings
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA38
SSLHonorCipherOrder off
#SSL Certificate
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
Lines 7-9 and 13 must be adapted to your own environment.
apache2ctl -t
systemctl reload apache2
systemctl status apache2
Configure certificate from Let's Encrypt
LetsEncrypt
apt-get install certbot python3-certbot-apache
Get certificate
certbot --apache
apache2ctl -t
systemctl reload apache2
systemctl status certbot.timer
Apache as reverse proxy incl. certificate from Let's Encrypt are now fully configured. Now we can start testing.
Tests
An external client is of course the best way to test whether the proxy is working properly. If no test computer is available at the moment, a VM can be quickly created in Azure or AWS and supplied with Outlook.
In my case, I used an Azure VM to test Outlook and OWA. In my case, Outlook and OWA work without any problems. In the event of an error, the Apache log files can help. The logs are saved under /var/log/apache2:
These two log files are relevant:
- exchange_443_access.log
- exchange_443_error.log
Do not be frightened by the HTTP 401 (Unauthorized) errors in the access log, this is a peculiarity of the NTLM protocol. The HTTP 401 errors should be followed by an HTTP 200 (OK) if the connection is successful:
Up to this point, you should have few problems with the reverse proxy, as the client connections are forwarded to Exchange almost unchanged.
Conclusion
Apache can be used quite easily as a reverse proxy for Exchange, but in my opinion this configuration does not provide any additional security. The configuration from this article is more suitable if other services are to be published on port 443 under a single public IP. With a little customization, it would be possible, for example, to route the connections to different servers depending on the DNS name.
At least this configuration ensures that the Exchange Admin Center is not accessible from the Internet. Most inquiries about reverse proxy and Exchange Server had the background that access to EAC from the Internet should be blocked. With Exchange 2019, however, this requirement can also be solved somewhat more easily:
Some readers only wanted to release certain protocols such as ActiveSync and OWA on the Internet, this is possible without any problems with the current configuration. For example, if you do not want to publish EWS, simply comment out this block from the Apache configuration:
#EWS
ProxyPass /ews https://${BackEndServerIP}/ews
ProxyPassReverse /ews https://${BackEndServerIP}/ews
ProxyPass /EWS https://${BackEndServerIP}/EWS
ProxyPassReverse /EWS https://${BackEndServerIP}/EWS
Things get more interesting in the next article, where mod_security is also used as a web application firewall (WAF).