Site icon Franky's Web

Apache as a reverse proxy for Exchange Server (Part 1)

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:

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).

Exit mobile version