AutoD-Weiche

Diese Seite beschreibt einen Service, um Anwender ohne Authentifizierung mit einem Verweis zum richtigen Exchange Server zu versorgen und damit mehrfache Eingaben von Anmeldedaten zu unterrücken.

Vorgeschichte

Microsoft hat für Exchange und Outlook mit Autodiscover eine pfiffige Lösung gefunden, damit ein Client den Weg zum Exchange Server findet. LDAP-Anfragen, DNS-Anfragen und Webservices liefern dem Client nach erfolgreicher Anmeldung letztlich eine XML-Datei mit der Konfiguration.

Selbst der Betrieb von mehreren Exchange Umgebungen ist abgedeckt, da ein Exchange Server über das Feld "TargetAddress" einen Client sogar zu einer anderen Organisation weiter leiten kann. Das ist für den Betrieb mit Exchange Online im Hybrid-Mode ebenso wichtig wie bei einer Cross-Forest Migration

Exchange Autodiscover liefert aber nur Daten, wenn der Benutzer sich gegenüber dem Exchange Server authentifiziert und es einen Mailuser mit Weiterleitung zur Zielumgebung gibt. Es gibt aber auch Systemumgebungen bei denen genau dies nicht möglich ist weil z.B. die Forests nicht per Trust verbunden sind, keine Kopplung per LAN/WAN erlaubt ist oder andere Umstände die native Funktion verhindern aber ein SMTP-AddressSharing oder Migrationsunterstützung erforderlich ist.

Die Planung

Benutzer arbeiten bislang mit Exchange im Forest1 und melden sich dort an. Zukünftig sollten Sie mit Exchange in Forest2 mit neuen Konten arbeiten aber neben der SMTP-Verbindung zum Routen gibt es sonst keine Verbindung. Wenn ich nun ein Postfach von Forest1 zu Forest2 verschiebe, kann ich in Forest1 durchaus das Postfach zu einen MailUser mit TargetAddress konvertieren. Für den Anwender wird der Start von Outlook auf einem eigenständigen PC aber zur Tortur:

  1. Outlook startet und kann per LDAP keinen Exchange Server finden
  2. Outlook landet per Autodiscover weiter auf Forest1
  3. Anwender muss Outlook die Anmeldedaten für Forest1 geben
  4. Outlook bekommt von Forest1 dann die Umleitung zu Forest2
  5. Outlook möchte Autodiscover gegen Forest2 machen
  6. Anwender muss Outlook die Anmeldedaten für Forest2 geben
  7. Jetzt erst die Outlook angemeldet

Wenn der Anwender die Zugangsdaten nicht "speichern" darf, dann kommen immer wieder solche Kennwortabfragen, z.B. bei Stellvertretungen etc.

Daher besteht der Plan, das der Eintrag "autodiscover.<domain>" weder auf dem Exchange Server im Forest1 noch Forest2 landet, sondern auf einem komplett eigenständigen Webserver, der die Anfragen des Clients sogar annimmt, in einer Lookup-Tabelle nachschaut und die Antwort liefert.

AutodiscoverV2 Redirect

Dazu müssen wir erst einmal sehen, wie der Redirect denn technisch funktioniert. Dazu eignet sich mein produktives Postfach in Exchange Online, da Autodiscover im Hybrid-Mode immer noch zum lokalen Exchange Server verweist. Mein Outlook stellt daher eine einfache anonyme Anfrage in der folgenden Form:

GET https://outlook.office365.com/autodiscover/autodiscover.json/v1.0/frank.carius@msxfaq.de?Protocol=Autodiscoverv1 HTTP/1.1
Connection: Keep-Alive
Accept: application/json
User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.14026; Pro)
client-request-id: A3D88AB8-7998-4D1B-A67B-5CC14C8AA0CF
Host: outlook.office365.com

Er bekommt als Antwort dann eine JSON-Struktur mit der Ziel-URL aber das hilft mir hier nicht weiter. Outlook hat nämlich gar nicht mehr bei "autodiscover.msxfaq.de" nachgefragt, sondern zuerst die Cloud gefragt.

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 97
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/10.0
request-id: 4a5ca9e7-e349-4bd5-af5c-b7d03d45b324
X-CalculatedBETarget: AM0PR04MB5489.eurprd04.prod.outlook.com
X-BackEndHttpStatus: 200
X-RUM-Validated: 1
X-AspNet-Version: 4.0.30319
X-DiagInfo: AM0PR04MB5489
X-BEServer: AM0PR04MB5489
X-Proxy-RoutingCorrectness: 1
X-Proxy-BackendServerStatus: 200
X-Powered-By: ASP.NET
X-FEServer: AM9P193CA0020
Date: Mon, 17 May 2021 20:11:05 GMT

{"Protocol":"Autodiscoverv1","Url":"https://outlook.office365.com/autodiscover/autodiscover.xml"}

AutodiscoverV1

Also habe ich mein bekanntes End2End EWS oder Test-EWS rausgeholt, welches ein "klassisches" Autodiscover macht. Hier sehen ich dann das übliche Bild:

Der Client geht anonym zu Autodiscover und fängt sich ein paar 401-Meldungen ein, bis er im Paket 23 dann einen authentifizierten Request stellt und eine Antwort bekommt. Mein Ziel ist es nun, schon auf die erste anonyme Anfrage zu antworten. Hier erst einmal die Anfrage in Paket 18.

POST https://autodiscover.msxfaq.de/autodiscover/autodiscover.xml HTTP/1.1
Content-Type: text/xml; charset=utf-8
Accept: text/xml
User-Agent: ExchangeServicesClient/15.00.0913.015
Host: msxfaq.de
Content-Length: 320
Expect: 100-continue
Connection: Keep-Alive

<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
  <Request>
    <EMailAddress>frank.carius@msxfaq.de</EMailAddress>
    <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
  </Request>
</Autodiscover>

Die Antwort aus Paket 23 sieht wie folgt aus:

HTTP/1.1 200 OK
Date: Mon, 17 May 2021 20:15:01 GMT
Server: Apache
Cache-Control: private
Content-Type: text/xml; charset=utf-8
request-id: 02fe2127-6c61-470e-9fe4-57a6ed23a23a
X-CalculatedBETarget: EX2016.msxfaq.de
X-DiagInfo: EX2016
X-BEServer: EX2016
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
X-FEServer: EX2016
Content-Length: 410
Set-Cookie: X-BackEndCookie=S-1-5-21-xxx-30417519-71842111-1009=xxx/xxx/xxx/xxx; expires=Wed, 16-Jun-2021 20:15:02 GMT; path=/autodiscover; secure; HttpOnly
Vary: Accept-Encoding

<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
  <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    <Account>
      <Action>redirectAddr</Action>
      <RedirectAddr>fcarius@msxfaq.mail.onmicrosoft.com</RedirectAddr>
    </Account>
  </Response>
</Autodiscover>

Ich denke mal, dass all die Header etc. vom Client nicht weiter beachtet werden und ich einfach "nur" die passende XML-Struktur in einem "200 OK" liefern muss.

PowerShell Webserver

Ich bin nun nicht der klassische ASP/ASP.NET Entwickler, der nun schnell auf einem IIS den Code erstellt. Vielleicht wäre das sogar der einfachste Weg. Aber auch per PowerShell kann ich schnell einen einfachen Webserver bauen. mit dem .NET-HTTPListener geht das recht einfach und schnell, da der "http.sys"-Stack im Windows Betriebssystem quasi die komplette HTTP-Steuerung übernimmt und mit NETSH die Zertifikate gebunden werden. Zur Nutzung des Skripts sind folgende Schritte erforderlich:

  • Windows PC mit PowerShell 7
    Die Installation eines IIS ist nicht erforderlich. Hier legen wir ein Verzeichnis an, in welches das Skript kopiert wird.
  • Ein Zertifikat für „autodisdover.<maildomain>
    Nur so kann Outlook über HTTPS unser Skript erreichen. Das Zertifikat muss mit privatem Key im Computerstore abgelegt werden.
  • Zertifikat binden
    Über NETSH tragen wir als Administrator das Zertifikat über den Thumbprint ein. Den Thumbprint erhalten ist in der PowerShell sehr einfach mit folgendem Befehl und können diesen dann auch mit NETSH eintragen.
# lokale Zertifikat auflisten
dir Cert:\LocalMachine\My

# Zertifikat binden. Bei Aufruf aus der PowerShell sind die {}-Klammen in " einzufasssen
# die AppGUID ist nicht relevant
netsh http add sslcert ipport=0.0.0.0:443 certhash=EBD1C1BE0E8632C28AB795F8DC5A7233E79966E2 appid="{00112233-4455-6677-8899-AABBCCDDEEFF}"
  • Windows Firewall
    Wenn das Skript nicht als Administrator gestartet wird, müssen Sie in der Windows Firewall den Port 443 noch eingehend öffnen.
  • Skript starten
    Wenn nun alle Voraussetzungen geschaffen sind, sollten Sie das Skript starten können.
  • Skript testen
    Als einfacher "Webserver" können Sie einfach per Browser den ersten Zugriff versuchen und das Zertifikat prüfen. Ich nutze dazu aber erst einmal eine lokale HOSTS-Datei, um den autodiscover.<maildomain> auf mein Skript zu lenken.
  • Hashtable füllen
    Ehe das Skript in den "Live-Betrieb" gehen kann, muss es natürlich mit Daten gefüllt werden. Ich habe mich gegen eine "Live Abfrage" per LDAP entschieden und lieber eine lokale CSV-Datei als Konfigurationsquelle vorbereitet, welche ein Administrator einfach durch eine neuere Version ersetzen kann. Das Skript liest die Datei per Default nach 2 Min neu ein oder über die URL "/reload" können Sie dies auch antriggern.
    So muss die AutoD-Weiche gar nicht im Intranet mit LDAP-Verbindung stehen. Die Einträge müssen natürlich aktualisiert werden, wenn ein Anwender "migriert" oder neu angelegt wurde. Das macht mein Skript nicht alleine.
  • Namensauflösung mit Hosts/DNS
    Wenn soweit alles funktioniert, können Sie den Service über eine Änderung im DNS dann auch allgemein zugänglich machen.

Beachten Sie, dass dieses Skript eine sehr einfache Version ohne umfangreiche Fehlerbehandlung ist. Insbesondere ein Monitoring der Erreichbarkeit und Funktion sollte extern bereitgestellt werden. Das Skript "test-autodweiche.ps1" kann dazu genutzt werden.

Einsatz

Direkt heraus: 99% der Firmen mit Exchange brauchen dieses Skript überhaupt nicht, denn die damit gelöste Problemstellung haben nur ganz ganz wenige Firmen. Wenn Sie das Skript einrichten und die Anleitung befolgen, dann ihre Umgebung sogar Probleme bekommen, wenn Sie die Zusammenhänge nicht komplett verstanden haben. Wenn Sie aber eine Umgebung haben, in denen diese Option weiterhelfen kann, dann wäre das Skript auch nur eine "Vorlage" für ein "Proof of Concept". Es ist aber nicht als "Dauerlösung" gedacht und muss auf jeden Fall angepasst werde.

Ich habe es daher aktuell noch nicht zum Download bereit gestellt, da es für sich allein keine Lösung darstellt. Sie können mir aber gerne erläutern, warum genau Sie ohne dieses Skript nicht mehr leben können.

Weitere Links