Apache als Reverse Proxy für Exchange Server (Teil 1)

Viele Leser dieses Blogs haben sich einen Artikel zum Thema „Exchange Server und Reverse Proxy“ gewünscht. Zwar gibt es hier schon HowTos mit Kemp, Sophos und F5, jedoch scheint es auch Bedarf an Open-Source Lösungen zu geben. Daher gibt es an dieser Stelle mal ein HowTo für die Nutzung von Apache als Reverse Proxy für Exchange Server.

Prinzipiell ist die Verwendung einen Reverse Proxys in Verbindung mit Exchange Servern eine gute Idee. Gerade in vielen kleinen Umgebungen wird oft ein simples NAT der Ports 80 und 443 am Router zum Exchange Server eingerichtet. Dies hat allerdings zur Folge, dass der Exchange Server mit all seinen Protokollen, Schnittstellen und Diensten im Internet veröffentlicht wird. Kommen dann noch vernachlässigte Updates oder Zero-Day Exploits hinzu, ist es nur eine Frage der Zeit bis dem Exchange Server Böses widerfährt.

Ein Reverse Proxy kann schon etwas Abhilfe schaffen, denn es lässt sich besser kontrollieren, welche Exchange Dienste veröffentlicht werden. Beispielsweise kann via Reverse Proxy der Zugriff auf das Exchange Admin Center deaktiviert werden. Einige Leser haben auch die Frage gestellt, wie nur OWA aus dem Internet erreichbar gemacht werden kann, alle anderen Protokolle wie ActiveSync oder MAPIoverHTTP aber nicht.

FunFakt: Viele automatisierten Angriffe laufen schon ins Leere, nur weil ein Reverse Proxy vorhanden ist. HTTP Header entspricht nicht „IIS“, dann auf zum nächsten Ziel…

In diesem Artikel geht es zunächst um die Installation und die Konfiguration von Apache als Reverse Proxy für Exchange. Im nächsten Artikel wird diese Konfiguration dann etwas erweitert.

Betriebssystem installieren

Als Betriebssystem habe ich Ubuntu Server 22.04 Minimal verwendet. Nach der Standardinstallation habe ich nur die Netzwerkkonfiguration durchgeführt, sowie NTP für die Zeitsynchronisation konfiguriert.

Ubuntu Server kann hier runtergeladen werden:

Ubuntu läuft bei mir in einer kleinen VM mit 2 vCPUs und 4GB RAM.

Firewall installieren und einschalten

Die Firewall UFW kann mit den folgenden Befehlen installiert und konfiguriert werden. Die Konfiguration lässt dabei alle ausgehenden Verbindungen zu, eingehend werden nur HTTP, HTTPS und SSH zugelassen:

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

Apache installieren und Module aktivieren

Damit Apache als Reverse Proxy für Exchange verwendet werden kann, muss Apache zunächst installiert und die notwendigen Module geladen werden:

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 als Reverse Proxy für Exchange Server

Apache als Reverse Proxy

cd /etc/apache2/sites-available/
a2dissite 000-default.conf
touch 001-exchange-proxy.conf
a2ensite 001-exchange-proxy.conf

In die Datei „001-exchange-proxy.conf“ kann nun die Proxy Konfiguration für Exchange eingefügt werden:

#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
<VirtualHost *:80>
        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}
</VirtualHost>

#HTTPS Virtual Host for Exchange Server
<VirtualHost *:443>
        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
        <Directory /Microsoft-Server-ActiveSync>
                SSLRenegBufferSize 31457280
        </Directory>

        #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

        <Directory />
                Order deny,allow
                Deny from all
        </Directory>

        <Proxy *>
                Order deny,allow
                Allow from all
        </Proxy>

        #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
</VirtualHost>

Die Zeilen 7-9 und 13 müssen an die eigene Umgebung angepasst werden.

apache2ctl -t
systemctl reload apache2
systemctl status apache2

Zertifikat von Let’s Encrypt konfigurieren

LetsEncrypt

apt-get install certbot python3-certbot-apache

Zertifikat holen

certbot --apache
Certbot

apache2ctl -t
systemctl reload apache2
systemctl status certbot.timer

Apache als Reverse Proxy inkl. Zertifikat von Let’s Encrypt sind nun schon mal fertig konfiguriert. Jetzt kann getestet werden.

Tests

Um zu testen ob der Proxy fehlerfrei funktioniert, eignet sich ein externer Client natürlich am besten. Falls gerade kein Testrechner zur Verfügung steht, lässt sich schnell eine VM in Azure oder AWS erstellen und mit Outlook versorgen.

In meinem Fall habe ich eine Azure VM benutzt um Outlook und OWA zu testen. In meinem Fall funktionieren Outlook und OWA problemlos. Im Fehlerfall können die Apache Logfiles weiterhelfen. Die Logs werden unter /var/log/apache2 gespeichert:

Apache Logs

Relevant sind die diese beiden Logfiles:

  • exchange_443_access.log
  • exchange_443_error.log

Lasst euch im Access Log nicht von den HTTP 401 (Unauthorized) Fehlern erschrecken, das ist eine Eigenheit des NTLM Protokolls. Auf die HTTP 401 Fehler sollte bei erfolgreicher Verbindung ein HTTP 200 (OK) folgen:

Apache als Reverse Proxy für Exchange Server (Teil 1)

Bis hierher solltet ihr wenig Probleme mit dem Reverse Proxy haben, denn die Verbindungen der Clients werden nahezu unverändert an Exchange weitergeleitet.

Fazit

Apache lässt sich recht einfach als Reverse Proxy für Exchange einsetzen, jedoch bringt meiner Meinung nach diese Konfiguration noch keinerlei Sicherheitsgewinn. Die Konfiguration aus diesem Artikel eignet sich eher, wenn unter einer einzelnen öffentlichen IP noch weitere Dienste auf Port 443 veröffentlicht werden sollen. Mit etwas Anpassung wäre es beispielsweise möglich die Verbindungen je nach DNS-Name zu unterschiedlichen Servern zu routen.

Immerhin sorgt diese Konfiguration schon einmal dafür, dass das Exchange Admin Center nicht aus dem Internet erreichbar ist. Die meisten Anfragen zum Thema Reverse Proxy und Exchange Server hatten den Hintergrund, dass der Zugriff auf EAC aus dem Internet blockiert werden soll. Mit Exchange 2019 lässt sich diese Anforderung allerdings auch etwas einfacher lösen:

Einige Leser wollten nur bestimmte Protokolle wie ActiveSync und OWA im Internet freigeben, dies ist mit der jetzigen Konfiguration problemlos möglich. Wer beispielsweise kein EWS veröffentlichen möchte, kommentiert einfach diesen Block aus der Apache Konfiguration aus:

        #EWS
        ProxyPass /ews https://${BackEndServerIP}/ews
        ProxyPassReverse /ews https://${BackEndServerIP}/ews
        ProxyPass /EWS https://${BackEndServerIP}/EWS
        ProxyPassReverse /EWS https://${BackEndServerIP}/EWS

Interessanter wird es im nächsten Artikel, denn dort kommt zusätzlich mod_security als Web Application Firewall (WAF) zum Einsatz.

32 Gedanken zu „Apache als Reverse Proxy für Exchange Server (Teil 1)“

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

    Antworten
  2. 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

    Antworten
  3. 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?

    Antworten
  4. 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

    Antworten
  5. 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.

    Antworten
    • 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

      Antworten
      • 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.

        Antworten
  6. 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

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

    Antworten
  8. 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

    Antworten
  9. 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

    Antworten
  10. 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

    Antworten
    • hat sich erledigt, nachdem ich bei „define BackEndServerIP“ nicht die IP sondern den Namen eintrage habe funktioniert der Zugríff auch mit Outlook

      Antworten
  11. 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

    Antworten
  12. 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.

    Antworten
  13. Wie schaut eigentlich die Konfig aus wenn man zusätzlich Webseiten bedienen möchte welche den selben Port verwenden, jedoch die selbe öffentliche IP?

    Antworten
  14. 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?

    Antworten
    • 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.

      Antworten
  15. 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 ?

    Antworten
  16. 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 ?

    Antworten

Schreibe einen Kommentar