WinHTTP, WinINET und Windows Proxy

Der Trend ist unübersehbar: HTTPS und HTTP ist das primäre Protokolle zum Übertragen von Daten zwischen Clients und Servern. Und 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.
  • 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.

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

 

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

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

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.

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

Weitere Links