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
![Certbot](https://www.frankysweb.de/wp-content/uploads/2022/05/image-8-1024x778.png)
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:
![Apache Logs](https://www.frankysweb.de/wp-content/uploads/2022/05/image-9.png)
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:
![Apache as a reverse proxy for Exchange Server (Part 1)](https://www.frankysweb.de/wp-content/uploads/2022/05/image-10-1024x106.png)
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).
Hallo,
ich habe auf dem EX2016 ein öffentliches Zert. installiert. Jedoch zeigen SSL Check immer noch ein selbst signiertes. Kann das der RP sein? Wenn ja, wie kann ich das Exchange Zert. verwenden, so dass die Check auch dieses anzeigen?
Frank
Hallo zusammen,
Exchange funktioniert einwandfrei mit diese Anleitung. Hat jemand einen Host für MS-Sharepoint erstellt?
Es will nicht so richtig bei mir.
Gruß
meleran
Ich würde gerne im Reverse Proxy noch einen Zweiten Server erreichen können der auf dem Port 8080 eine Webseite hostet.
Am besten https mit redirect von http auf https.
Kann mir hier irgendwer helfen, wie ich das in die Config eintragen muss, damit das funktioniert?
Hallo,
auch wenn hier schon etwas ruhe drin ist…
wie ist wäre denn die Config-Header für zwei Domain’s?
Beispiel owa.domain1.de und owa.domain2.de
Muss denn für die ExchangeExtendedProtection nicht auch noch etwas hinzugefügt /angepasst werden?
Grüße
schade, dass die Durchführung der Schritte schon zu Beginn scheitert!
nach der Änderung der apache2.conf startet der Dienst nicht mehr, da ihm die letzte Zeil nicht passt.
Ändern geht nicht – kein Editor.
mit winscp oder filezilla runterladen, ändern, hochladen -> geht nicht, keine Berechtigung als „admin“ (=User, der beim Setup eingerichtet worden ist. Der darf NICHTS!)
Login als root – verweigert.
Auf Deutsch: das geht nicht, hier steht man überall an.
Deine Methode Linux-Server zu verwalten erscheint mir sehr abenteuerlich.
Einen dieser Editoren wird es auf deinem Server ganz sicher geben. Damit kannst du die Datei bearbeiten:
nano
vi
vim
Durchaus üblich, sich eine Textdatei mit winscp auf einen Windows-Rechner zu kopieren, dort zu editieren (aus meiner Sicht sinnvoll, Notepad++ zu verwenden) und wieder hochzuladen.
vi ist nicht sehr anwenderfreundlich, besonders dann, wenn man mit einem Mac arbeitet und dabei die Steuerungstasten nicht funktionieren. Sicher, kann man auch abenteuerlich sehen, ich sehe es eher sicherer.
Allerdings muss ich für winscp auch auf ein Windows-Gerät zurückgreifen, das ist aber eine von ganz wenigen Ausnahmen.
Und nein, keiner der 3 Editoren war installiert, ich habe die Minimal-Installation bevorzugt.
super simpel wäre es, wenn outlook mit client certs umgehen könnte für die Verbindung. Aber das geht meines Wissens nach nicht.
Was im Browser einfach funktioniert, geht im Full Client nicht..
Mit NGINX sind dasss dann irgendwie zwei Zeilen
# custom config
ssl_client_certificate /etc/ssl/caxyz.pem;
ssl_verify_client on; # von off auf on gestellt
Super Anleitung, erstmal vielen Dank dafür, war schon lange auf der suche und hab auch schon einiges versucht.
Es funktioniert auch soweit alles bis auf eine Kleinigkeit.
Das Persönliche Archive (In-Situ-Archiv) bekommt Outlook keine Verbindung mehr hin.
Ich hab einen Exchange Server 2016.
Hat jemand auch das Problem und vielleicht schon eine Lösung die er mit mir teilen möchte? :-)
Ich weis die Archiv Funktion vom Exchange werde wahrscheinlich die wenigsten benutzen.
Ich dachte ich frag dennoch mal. :-)
Danke im Voraus für eure Hilfe.
Wir wollten in diesem Setup noch das Exchange Control Panel (ecp) von extern blockieren und haben festgestellt, dass es in diesem Setup auf /owa/ecp umgeleitet wird, was dann zwar auch nicht funktioniert (was erwünscht ist) aber wir keine Einstellung in dieser Konfig gefunden haben, die das veranlasst. Weiß jemand wo das herkommt?
Btw: Danke für diese Anleitung, dass hat nahezu unverändert, so wie es hier dokumentiert ist, funktioniert. Kleinere Anpassungen, zB an die Servernamen waren ja eh zu erwarten. Für den zweiten Teil der Anleitung (mod_security) warten wir jetzt noch, ob bis hierher alles stabil läuft.
Thx & Bye Tom
Hallo Tom,
wie hast du das Gelöst da ich das auch habe wurde mich über Infos freuen.
MFG
Patrick
Hallo Frank,
der link –> https://www.frankysweb.de/exchange-2019-client-access-rules ist leider nicht mehr verfügbar kannst du das mal fixen.
Danke
MFG
Patrick
Hi,
ich habe das Tutorial relativ zügig nach Erscheinen umgesetzt und zunächst hat auch alles funktioniert. Jetzt verbindet sich Outlook nicht mehr und es erscheint ständig eine Passwortabfrage.
Intern, also ohne Apache rproxy, funktioniert alles.
Viele Grüße
Jens
Hallo,
sehr schöne Anleitung, danke dafür
ich nutze das unter Debian 11 mit einem Exchange 2016 CU22
Aufruf des OWA und Login ist kein Problem, vom Handy aus ebenfalls alles ok
Jedoch verbindet sich MS Outlook nicht mehr wenn man von extern darauf zugreift, es wird ständig nach dem Passwort gefragt. Was muss ich tun um das zu verhindern?
Danke
hat sich erledigt, nachdem ich bei „define BackEndServerIP“ nicht die IP sondern den Namen eintrage habe funktioniert der Zugríff auch mit Outlook
Schönen guten Tag,
ich habe ein „Problem“ mit dem Reverse Proxy beim erneuern des Let`s Encrypt Zertifikates auf dem Exchange Server.
Dieses ist mit dem Tool nicht mehr möglich, er hat eine Fehlermeldung angezeigt, dass er auf einer bestimmten URL keine Antwort oder die falsche Antwort bekommen hat.
Schalte ich den Proxy aus und klemme den Exchange wieder direkt ins Netzt, geht es ohne Probleme.
Der Proxy „blockt“ also wohl irgendwelche Anfragen die das Script für Let`s Encrypt braucht.
Gibt es da eine Möglichkeit, dieses Verhalten zu beheben?
mfg
Super Anleitung, Frank. Vielen lieben Dank :-)
Ich habe mich jetzt gestern und heute schon relativ intensiv damit befasst. Soweit funktioniert das auch alles.
Allerdings hänge ich jetzt an dem Problem, dass die Outlooks von extern, welche also über den Reverse Proxy zum Exchange möchten, immer wieder die Verbindung verlieren und dann die Aufforderung zur Eingabe der Credentials erscheint. Eine Recherche ergabe, dass das wohl mit der Art und Weise zu tun hat, wie Outlook die RPC-Anfragen in HTTP(S) verpackt.
Es gab da wohl auch mal ein Modul Namens „libapache2-mod-proxy-msrpc“, das genau dafür gedacht war. Nur ist das für die aktuelle Version Ubuntu nicht mehr kompatibel / bzw. nicht mehr in den Paketlisten. Hat noch jemand die Erfahrung gemacht, dass die externen Outlooks über Outlook Anywhere ein Problem haben? Und wenn ja, konntet Ihr das lösen?
Wäre cool, wenn da jemand von Euch was weiß dazu.
Eine Option wäre den Exchange-Cache-Modus anzupassen und diesen zu verkleinern.
Zusätzlich würde ich die Apache Konfiguration prüfen: /etc/apache2/server-tuning.conf (nutze openSUSE)
Z.B.:
…
# highest possible MaxRequestWorkers setting for the lifetime of the Apache process.
# https://httpd.apache.org/docs/2.4/mod/mpm_common.html#serverlimit
ServerLimit 500
# maximum number of server processes allowed to start (formerly MaxClients)
# https://httpd.apache.org/docs/2.4/mod/mpm_common.html#maxrequestworkers
MaxRequestWorkers 500
MaxKeepAliveRequests 10000
…
Das könnte das Problem schon beheben.
Ja, das war ein super Hinweis, vielen Dank.
Ich habe gestern noch etwas weiter gesucht, und konnte dann unter folgendem Link das Modul „libapache2-mod-proxy-msrpc“ herunterladen und installieren: https://ubuntu.pkgs.org/20.04/ubuntu-universe-amd64/libapache2-mod-proxy-msrpc_0.6-1_amd64.deb.html
Das alleine hat aber das Problem noch nicht behoben, aber die Intervalle zwischen den Passwort-Abfragen verlängert.
Final gelöscht habe ich es jetzt tatsächlich mit Deinen Ergänzungen. Also: Nochmals vielen Dank :-)
RPC over HTTP ist eigentlich steinaltes Gemüse und sollte so gar nicht mehr zum Einsatz kommen¹.
Mich würde es wundern, wenn das bei Dir noch im Einsatz wäre.
¹ https://learn.microsoft.com/de-de/exchange/troubleshoot/administration/rpc-over-http-end-of-support
Wie schaut eigentlich die Konfig aus wenn man zusätzlich Webseiten bedienen möchte welche den selben Port verwenden, jedoch die selbe öffentliche IP?
Ja, das würde mich auch interessieren.
Dem schließe ich mich an :-)
Wie sieht es denn mit KeepAlive aus, gerade in Hinsicht auf ActiveSync?
Der Link auf
https://www.frankysweb.de/exchange-2019-client-access-rules/
am Ende des Textes läuft auf einen „not found“ Fehler.
Danke für die gute Anleitung.
Ein Problem habe ich nun, am Exchange in den Logins sehe ich nun nur noch die IP des Proxy, nicht aber die IP der Anfrage.
Nun funktioniert das Fail2ban auf dem Exchange leider nicht mehr, bzw. wird der Proxy nun ausgesperrt.
Gibt es eine Option das am Exchange auch die eigentliche IP geloggt werden kann, fürs fail2ban?
@MaGo NAT für Port 25 so umbauen, das es direkt auf den Exchange Server zeigt. Der Reverse Proxy ist nur für HTTP und HTTPS.
Dankeschön, habe auf der Ubunut Kiste jetzt „Haproxy“ laufen, der den Port 25 weiterleitet, läuft ohne Probleme.
Trotzdem danke für die Info.
Habe noch ein anderes Problem.
Nun habe ich von außerhalb keinen kontakt mehr zum Exchange auf Port 25. Wie behebe ich dieses Problem?
Hi,
„“Die Zeilen 7-9 und 13 müssen an die eigene Umgebung angepasst werden.““
da bist du etwas in den Zeilen verrutsch ?
Zeilen 6-8 und 11 ?
Cooles Tutorial, bin aufs nächste umso mehr gespannt :)
Eine wirklich gute Anleitung, danke dafür.
Ich habe nur eine Frage.
Ich hatte davor die exchange und die autodiscover URL per DNS auf den Exchange Server geroutet.
Jetzt habe ich die IP des Exchange Servers geändert und dem Reverse Proxy diese IP gegeben.
Von außerhalb hat es ohne Probleme funktioniert, nur von Intern sagte Outlook nun andauernd, dass die Passwörter falsch sind.
Habe dann für intern die exchange und autodiscover URL auf die neue IP des Exchange Servers geroutet und nun funktioniert alles wie es soll.
Ist das in Ordnung so oder ist das ein merkwürdiges Verhalten ?
Intern den Remote Proxy davor zu haben ist ja nicht zwingend nötig oder ?