Windows Proxy Konfiguration

HTTPS und HTTP sind das primäre Protokolle zum Übertragen von Daten zwischen Clients und Servern. Damit meine ich nicht nur das klassische "Surfen" im Web mit den multimedialen Inhalten wie Audio (Internetradio) oder Videos (YouTube und Co). HTTPS wird auch bei der Kommunikation zwischen Servern (Siehe Kalenderfederation) und für die Überprüfung von Zertifikaten (Siehe CRL) genutzt.

Aber auch HTTP hat die Herausforderung Netzwerkgrenzen mit privaten und öffentlichen IP-Adressen und Firewall-Filter zu überspringen. Während im Homeoffice-Bereich dies durch DSL-Router mit NAT noch sehr einfach ist, gilt es bei Firmen durchaus andere Anforderungen zu meistern. Hier ist in der Regel ein HTTP-Proxy im Einsatz, der auf dem Client einmal konfiguriert werden will, der aber zudem auch eine Authentifizierung anfordern kann und die angefragten URLs prüft, filtert und auch die Antworten eventuell auf ihre Gefährlichkeit bewerten kann. Wenn ein Client oder Server aber nur unter Nutzung eines Proxy-Servers externe Dienste ansprechen kann, dann gilt es heraus zu finden, wie dies konfiguriert werden kann.

HTTP unter Windows

Wenn Clients einen Webserver ansprechen wollen, dann können sie zwar selbst auf Basis von TCP-Sockets einen HTTP-Stack implementieren, aber einfacher ist die Nutzung von bereits vorhandenen Komponenten. Dazu gibt es unter Windows und im .NET-Framework fertige Klassen, die einfach verwendet werden können. Aber da es gleich mehrere Klassen gibt, verhalten Sie sich auch an einigen Stellen unterschiedlich. Genau genommen kenne ich vier Optionen:

  • WinINET
    Dies ist eine generische API, die Anwender und Programme einfach nutzen können. So nutzt auch der Internet Explorer diese Komponente. Wer also hier die Proxy-Konfiguration "richtig" macht, hat damit auch alle Programme konfiguriert, die diese Schnittstelle nutzen. Die größte Einschränkung von WinINET im Bezug auf den Einsatz für Server und Skripte ist die Möglichkeit, eine GUI anzeigen zu wollen. So kann es passieren, dass WinINET einen Dialog anzeigen will um z.B. Zertifikatswarnungen zu melden, Anmeldedaten abzufragen etc. Daher ist WinINET eher für interaktive Programme geeignet.
  • WinHTTP
    Dies ist eine "Server"-Klasse und wird daher meist von Produkten genutzt, die in .NET programmiert wurden. Proxy-Einstellungen sind separat zu steuern. Exchange Server sind z.B. solche Kandidaten. Der Funktionsumfang von WinHTTP ist etwas einfacher und sie sind gut beraten, viele Einstellungen vorzugeben und eine saubere Fehlerbehandlung umzusetzen.
  • NET-Framework Proxy
    Auch die .NET-Programme haben eine eigene Proxy-Konfguration. Diese kann pro Maschine, Pro User und pro Programm vorgegeben werden (machine.config) oder beim Aufruf der entsprechenden Methode im Code hinterlegt werden.
  • 3rd Party Komponenten / Eigenbau
    Natürlich kann jemand auch eine Komponente eines Drittherstellers nutzen oder gleich ganz den HTTP-Stack samt Proxy-Authentifizierung nutzen.

Diese verschiedenen Modelle unterscheiden sich schon bezüglich der Proxy-Konfiguration und wer diese nutzt.

Wer nutzt das ?

Die bekannten Browser wie Internet Explorer, Microsoft Edge aber auch Chrome nutzten einfach den Windows IP-Stack, um sich per HTTP mit Webdiensten zu verbinden. Wenn der Zugriff über einen Proxy erfolgt, dann können Sie im Internet Explorer oder der Systemsteuerung den Proxy eintragen. Diese Eintragungen sind aber für den "CurrentUser" vorgegeben. Andere Programme nutzen gerade nicht WinHTTP, sondern haben sich was eigenes gebaut.

Dienst WinHTT Anmerkungen

Internet Explorer

WinINet

Nutzt die Windows Proxy Einstellungen des Users
Ab IE11 ist die Nutzung von "File-URLs für WPAD-Dateien per Default abgeschaltet. Über einen Registrierungsschlüssel kann es wieder eingeschaltet werden.

Key:   HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ 
Value: EnableLegacyAutoProxyFeatures 
Type:  REG_DWORD 
Data:  1

Chrome

WinINet

Nutzt die Windows Proxy Einstellungen des Users

Firefox

WinINet

Nutzt eigene Proxy Einstellungen. WinINET wird nur genutzt, wenn die Proxy Einstellungen auf "System" stehen

PowerShell

WinHTTP

In der PowerShell gestartet Commandlets wie Invoke-Webrequest u.a. werden nicht die Einstellungen im IE (WinINET) aus, sondern WinHTTP. Siehe auch PS HTTPClient

.NET Applikationen

WinINet

Die meisten Programme lesen die Proxy Einstellung nur beim Start aus aber nicht mehr während der Laufzeit. Einige nutzen aber die .NET Klassen und benötigen eine Konfiguration in der machine.config

WinRM

WinHTTP

Nutz die WinHTTP-Einstellungen von LocalComputer

WinRM

Windows: CRL Abfragen von LocalSystem

WinHTTP

Nutz die WinHTTP-Einstellungen von LocalComputer

Windows: Update der Root-Zertifikate

WinHTTP

Nutz die WinHTTP-Einstellungen von LocalComputer

Windows: Windows Updates

WinHTTP

Nutz die WinHTTP-Einstellungen von LocalComputer

Exchange 2016 Malware Update (BITS)

WinHTTP

Nutz die WinHTTP-Einstellungen von LocalComputer

Exchange CAS-Server

Eigen

Exchange wird getrennt konfiguriert

Lync Server

WinHTTP

Lync nutzt WinHTTP aber patzt bei einer PAC-Datei, die als File-URL bereitgestellt wird.

Skype for Business Server

WinHTTP

 

Lync/SfB Client

WinHTTP

 

ADFS

 

WAP

 

Office 365 Anmeldeassistenz

Nutzt die Windows Proxy Einstellungen des Users

IIS AAR

 

IIS WebApps

web.config

Applikation im IIS laufen in der Regel als "Network System" und nutzen den Systemproxy des Internet Explorers, der bei Network System aber eigentlich nicht da ist. Sie können die Proxy-Konfiguration über die web.config entsprechend hinterlegen.

 

Das geht sogar über die GUI

Ich habe noch nicht alle Programme bezüglich ihrer Proxy-Funktion analysieren müssen. Diese Liste wird weiter geführt.

Proxyeinstellungen mit WinHTTP

Abhängig vom genutzten Modul ändert sich auch der Weg, die Proxy-Einstellungen vorzunehmen. Schon abhängig vom Betriebssystem auf dem Client gibt es unterschiedliche Programme zur Konfiguration per Kommandozeile:

  • proxycfg.exe (XP) 
    netsh.exe (Vista und höher)

Die Einstellungen wirken zwar auf den Internet Explorer und meist auch nicht auf andere Browser. Sie gelten aber für Systemkomponenten, die Zugriff auf das Internet brauchen und keine eigene Konfiguration bereitstellen.

Interessant ist dazu auch folgende Aussage:

WinHTTP Considerations
Thanks to Eric Loewenthal, owner of WinHTTP's proxy code, für providing the expertise für this section
The WinHTTP stack was designed für use in services and other contexts where WinINET would be inappropriate (e.g. because WinINET may show UI or not scale well für unattended use). WinHTTP offers a limited subset of proxy support-- generally speaking, the calling code is expected to set the proxy configuration settings directly on the session or request objects. The User may attempt to configure the "default" proxy für WinHTTP using the proxycfg.exe (XP) or netsh.exe (Vista+) tools, but these tools only support fixed proxy settings (not autodetection or PAC script URLs) and WinHTTP-based applications may or may not use those settings.
The configuration tools were primarily intended or WinHTTP apps that are running as System (without a User to impersonate).
Quelle: http://blogs.msdn.com/b/ieinternals/archive/2013/10/11/web-proxy-configuration-and-ie11-changes.aspx?PageIndex=2

Note: not process a proxy script if the Content-Type response header is not "application/x-ns-proxy-autoconfig" or the URL's file extension is not one of .js, .pac, or .dat. Also, remember that WinHTTP will not use proxy script files from file:// URLs, on any version of Windows.
Quelle: http://blogs.msdn.com/b/ieinternals/archive/2013/10/11/web-proxy-configuration-and-ie11-changes.aspx?PageIndex=2

REM Einstellungen des Internet Explorer (WinINET) nach WinHTTP übernehmen
netsh winhttp import proxy ie

REM Einstellungen manuell setzen
netsh winhttp set proxy proxy-server="http://proxy.msxfaq.de:3128" bypass-list="*.msxfaq.de,*.msxfaq.local,<local>"

REM Aktuelle Einstellungen anzeigen
netsh winhttp show proxy

Proxy-Einstellungen in WinINet

Die klassische Einstellung von WinINet erfolgt über den Internet Explorer:

Alternativ kann die Einstellung natürlich auch über Gruppenrichtlinien auf Gruppen von Systemen verteilt werden. Insbesondere die Konfiguration über Gruppenrichtlinien auf "AD-Sites" statt auf OUs ist eine interessante Option geografisch naheliegende Proxy-Server zu verwenden. Allerdings ist so eine Konfiguration nicht immer dynamisch genug, um Wechsel des Clients zwischen Netzwerken (LAN, WLAN, UMTS) entsprechend abzudecken. Zudem wirken Gruppenrichtlinien nur auf Windows Clients in der Domäne aber nicht auf Smartphones, Tablets, Fremdsysteme etc

Ich bevorzuge die Konfiguration per WPAD, da hier z.B. per DHCP oder DNS die Proxy-Dienste viel flexibler zugewiesen werden können und alle WPAD-tauglichen Systeme unabhängig von der Zugehörigkeit einer Domäne die Konfiguration erhalten können.

One of the most influencing differences between WinINET (which Internet Explorer uses) and WinHTTP (which Outlook obviously uses) is the missing conversion from upper-case characters to lower-case characters when it comes to the evaluation of a proxy-script (WPAD).
Therefore the parameters which the script is feed should be converted to lower-case before evaluating them in the script.
As I've seen in the provided scripts, you use the "url"-parameter in addition to the host-parameter, the following statements should be included in the WPAD.DAT:
url=url.toLowerCase();
host=host.toLowerCase();
This side-effect is also mentioned in the following blog-post: http://blogs.technet.com/b/emeaie/archive/2013/11/04/optimizing-performance-with-automatic-proxyconfiguration-scripts-pac.aspx

... if you check both the "Automatically Detect Settings" and "Automatic Configuration Script" boxes, auto-detection takes precedence, regarding auto-configuration and manual proxy server, the automatic configurations will take precedence over manual configuration. ...
https://social.technet.microsoft.com/Forums/windows/en-US/a92d8eb9-bb21-4b16-afd4-ea9581b7b882/ie-proxy-setting-selection-orderpriority?forum=w7itprogeneral

4. Javascript is case-sensitive
The proxy script uses the language javascript, which is case-sensitve. Therefore an if-clause where upper characters are used will never turn true, while the other parameter is using lowercase. Internet Explorer itself converts the variables host and url into lowercase before the function  FindProxyForURL is called. This is not true für WinHTTP, which passes the hoist and the url directly to the function.
Therefore the parameters, which are checked within the PAC-file should be converted within the PAC before they are evaluated. Here is the call für the convert:      host = host.toLowerCase();
Quelle: Optimizing Performance with automatic Proxyconfiguration scripts (PAC)
http://blogs.technet.com/b/emeaie/archive/2013/11/04/optimizing-performance-with-automatic-proxyconfiguration-scripts-pac.aspx

Proxy in Machine.config

Programm, die auf einem .NET-Framework aufsetzen, können nicht nur theoretisch auf anderen Plattformen als Windows laufen. Eine PowerShell auf eine Raspberry ist nur eine extreme Form. Damit kann eine Software auch nicht immer davon ausgehen, dass es eine Registrierung gibt oder mit WinINet ein HTTP-Stack als COM-Objekt oder ein "Internet Explorer" bereit steht, der sich um die Fragen des Proxy-Servers kümmert.

.NET-Programme werden daher schon immer auch über eine "CONFIG-Datei" gesteuert, die z.B. als "PROGAMMANME>.CONFIG neben der EXE-Datei im Verzeichnis liegt. In dieser XML-Datei könnten unterschiedlichste Aspekte des Programms konfiguriert werden. In dieser XML-Datei kann es unter "<configuration><system.net>" auch eine Sektion "<DefaultProxy>" geben. Hier ein Beispiel

<configuration>
  <system.net>
    <defaultProxy>
      <proxy
        usesystemdefault="true"
        proxyaddress="http://192.168.178.50:8888"
        bypassonlocal="true"
      />
      <bypasslist>
        <add address=".*\.msxfaq\.com$" />
        <add address=".*\.uclabor\.de$" />
      </bypasslist>
    </defaultProxy>
  </system.net>
</configuration>

Manchmal möchten Sie auch einen per WPAD o.ä. bereitgestellten Proxy extra umgehen, dann können Sie dies wie folgt erzwingen:

<configuration>
  <system.net>
    <defaultProxy enabled="False">
      <proxy
        autoDetect="False"
        usesystemdefault="true"
        proxyaddress="http://localhost:1234"
        bypassonlocal="true"
      />
      <bypasslist>
        <add address="*." />
      </bypasslist>
    </defaultProxy>
  </system.net>
</configuration>

Damit ist AutoConfig abgeschaltet und mit bypassonlocal="True" und passender Bypasslist umgehen alle Ziele den Proxy

Wenn sie eine bestehende XML-Datei vorfinden, dann müssen Sie die Einstellungen dort korrekt einbinden. Der Root-Knoten <configuration> ist vermutlich schon da und vielleicht ist auch <system.net> noch vorhanden, so dass Sie ihre Proxy-Einstellungen dort drunter addieren müssen. Beachten Sie bei der Bypass-List die Verwendung der regulären Ausdrücke.

Diese Konfigurationsdatei gibt es aber nicht nur für das Programm selbst, sondern auch als globale "machine.config" im .NET Programmverzeichnis. Eine Suche unter "%Windir%\Microsoft.NET\Framework" liefert bei mir auch schon mehrere Config-Dateien:

Beachten sie auch hier, dass es auf einem Computer sowohl 32bit als auch 6b4-Versionen und unterschiedliche Versionen nebeneinander geben kann und daher mehrere "machine.config"-Dateien vorhanden sein können.

Debugging von WinHTTP

Um Zugriffe untersuchen zu können, die die Systemkomponenten "WinHTTP" nutzen, hat Microsoft eine Trace-Schnittstelle eingebaut.

REM Tracing aktivieren

netsh winhttp set tracing trace-file-prefix="%Userprofile%\desktop\trace\log" level=verbose format=hex state=enabled max-trace-file-size=52428800

netsh winhttp set tracing trace-file-prefix="C:\Temp\dpws" level=verbose format=ansi state=enabled max-trace-file-size=1073741824

REM Tracing wieder abschalten
netsh winhttp set tracing state=disabled
C:\Windows\system32>netsh winhttp set tracing
will show you the options:
Usage:  set tracing
        [output=]file|debugger|both
        [trace-file-prefix=]<string>
        [level=]default|verbose
        [format=]ansi|hex
        [max-trace-file-size=]<number>
        [state=]enabled|disabled

Alternativ kann ein Tracing auch im Eventlog aktiviert werden. Für die Freund der GUI hier ein Bild:

Diese Einträge sind aber nicht so umfangreich wie das Tracefile und werden in den Eventlog geschrieben.

Unabhängig von diesem Trace ist mein primäres Tool immer noch der Blick auf ProxyLogs und insbesondere. Fiddler. Fiddler stellt zumindest schon die Einstellungen von WinINET alleine um. Ich muss mit daher nur noch um eine passende Konfiguration für WinHTTP küommern.

Outlook mit HTTP-Proxy

Durch einen Supportfall bin ich auf ein etwas seltsames Verhalten mit Outlook 2010 in Verbindung mit MAPI/HTTP gestoßen worden. In dem Fall war der Anwender am PC mit seinem Benutzernamen angemeldet. In Outlook hat er sich aber mit einem anderen Postfach auf dem Exchange 2016 Server verbunden. Er musste also bei jedem Start einmal den anderen Benutzernamen samt Kennwort eingeben. Der Anmeldebenutzer hatte also keinen "Vollzugriff" auf das Postfach.

Solange kein Proxy-Server eingetragen war, hat der Zugriff problemlos funktioniert. Wurde aber in den Internet-Einstellungen ein Proxy-Server statisch eingetragen und die Exchange-URL (MAPI/HTTP) als Ausnahme definiert, dann konnte Outlook keine Verbindung mehr herstellen. Mit Wireshark wurde bewiesen, dass der Client auch die Ausnahmen respektiert. Wir haben dann vermutet, dass Outlook beim ersten Kontakt zu Exchange die Anmeldedaten erfragt und sich mit dem Exchange Adressbuch-Dienst verbinden kann. Für die Verbindung zum Postfach dürfte Exchange erneut eine Anmeldung anfordern, die WinHTTP diesmal aber nicht mit den vorher manuell eingegeben Anmeldedaten beantwortet, sondern die Daten des an Windows angemeldeten Benutzers sendet. Der Benutzer hat allerdings keine Rechte und Outlook beendet sich mit einem Fehler, dass der Postfachspeicher nicht geöffnet werden kann. Interessanterweise tritt das Problem nicht auf, wenn der Proxy über eine PAC-Datei konfiguriert wird. Ob das Problem nun speziell mit Outlook 2010, Windows 7 oder dem Exchange 2016 Server zusammenhängt, wurde nicht weiter analysiert. Die Proxies werden nun per PAC-Datei konfiguriert, was sowieso eine größere Flexibilität ermöglicht.

Exchange mit HTTPProxy

Nicht alle Produkte und Dienste nutzen immer die von Microsoft Windows bereitgestellten WinINET oder WinHTTP-Libraries. Das können Produkte sein, die z.B. nicht auf Windows beschränkt sind, sondern so portabel entwickelt sind, dass sie auch auf anderen Plattformren laufen können und daher sowohl den HTTP-Stack als auch Proxy-Einstellungen selbst verwalten. Das gilt aber zum Teil auch für .NET Code und selbst Microsoft Exchange nutzt ab Exchange 2010 nicht mehr zwingend den "System-Proxy" sondern erlaubt eine manuelle Konfiguration über Set-ExchangeServer.

Set-ExchangeServer `
   -Identity "EX2016A" `
   -InternetWebProxy http://proxy:8080

Damit wird der Exchange Server "Ex21016A" angewiesen alle HTTP-Anfragen über den Proxy zu leiten. Das ist insbesondere für CRL-Abfragen etc. wichtig oder auch die Zugriffe auf das Microsoft Federation Gateway und später auf andere Exchange EWS-Zugangspunkte z.B. für die Abfrage von Frei/Belegt-Zeiten (Kalenderfederation:E2010/2013 und Kalenderfederation:Office 365)

.NET Code und HTTPProxy

Früher gab es "INI-Dateien" und später die Registrierung. Bei .NET Programmem gibt es in der Regeln neben jeder EXE oder DLL auch eine Konfigurationsdatei mit der Endung ".CONFIG". Dies ist eine XML-Datei, in der sie vielleicht den folgenden Abschnitt finden:

<configuration>
  <system.net>
    <defaultProxy>
      <proxy bypassonlocal="false" usesystemdefault="true" />
    </defaultProxy>
  </system.net>
</configuration>

Und natürlich können Sie die Zeile "Proxy" auch anpassen. Hier ein Beispiel:

<configuration>
  <system.net>
    <defaultProxy>
      <proxy autoDetect="false" bypassonlocal="false" proxyaddress="http://proxy:8080" usesystemdefault="false" />
    </defaultProxy>
  </system.net>
</configuration>

Es ist aber nicht garantiert, dass jede .NET Applikation sich dieser Einstellungen bedient. Ein Entwickler kann die Einstellungen auch anderswo auslesen und die Konfiguration selbst setzen. hier ein Beispiel aus einem Code. Zuerst wird ein WebRequest-Objekt instanziert, welches dann über das Property "Proxy" eine abweichende Konfiguration erhält:

objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Proxy= new WebProxy("Proxy", 8080);

IIS Apps und Proxy-Servers

Etwas anders verhält es sich mich Applikationen, die im IIS instanziert werden. ASPX ist quasi die Ablösung von ASP und auch Request Handler können als NET-Module die Funktion eines IIS erweitern. Exchange Online aber auch vor allem Skype for Business nutzen diese Möglichkeit.

Nun gibt es aber Funktionen, die ihrerseits einen Zugriff auf das Internet erforderlich machen, z.B. Abruf von CRLs oder die FederationMetadata eines ADFS-Servers oder Office 365 evoSTS (Siehe auch Hybrid Modern Authentication oder OAUTH2 / Modern Authentication) Diese Module werden über eine "web.config" konfiguriert und nutzen per Default den Systemproxy von "Network System".

Die Konfiguration der Web.Config ist einfach per Editor möglich oder auch über die IIS Verwaltungstool.

Zuerst gehen Sie auf das virtuelle Verzeichnis und starten Sie den "Configuration Editor" im mittleren Abschnitt. Im folgenden Fenster können Sie dann in der Sektion auf "system.net" gehen und den Proxy eintragen:

Wenn Sie den Bereich "proxy" aufklappen, dann sehen Sie die aktuellen Einstellungen:

Weitere Links