Unternehmensproxy und Windows-Apps — Proxyauflösung in WinINET, WinHTTP und .NET sortieren

· · Windows, Proxy, WinHTTP, WinINET, .NET, HttpClient, PAC, WPAD, Netzwerk

„Der Browser öffnet externe Sites, aber nur die Geschäftsanwendung erreicht die externe API nicht.“ „Auf der Entwicklungsmaschine funktioniert es, aber im Kundennetzwerk läuft es in den Timeout.“ „Es kommuniziert, wenn ich es von Hand starte, und scheitert, sobald ich daraus einen Windows-Dienst mache.“ — Wenn Sie eine Geschäftsanwendung in einer Umgebung mit Unternehmensproxy betreiben, gehört diese Art von Anfrage zu den häufigsten.

In den meisten Fällen ist die Ursache weder ein Proxy-Server-Ausfall noch ein App-Fehler. Windows hat mehrere getrennte Familien dessen, was Leute „Proxyeinstellungen“ nennen, und welche Einstellungen wer liest, unterscheidet sich nach App (nach dem HTTP-Stapel, den sie verwendet) und nach Ausführungskonto — dieses Missverhältnis. Die Einstellungen, die der Browser liest, die ein Dienst liest und die .NET-HttpClient liest, können jeweils etwas anderes sein. Sobald diese Struktur im Kopf ist, wird das Isolieren von „es funktioniert im Browser, aber …“ überraschend schnell.

Dieser Artikel richtet sich an IT-Personal in kleinen und mittleren Unternehmen und an Windows-App-Entwickler. Er verbindet in einem Bild die drei Familien von Proxyeinstellungen — WinINET, WinHTTP und Umgebungsvariablen —, PAC- und WPAD-Autokonfiguration, den Unterschied der Proxyauflösung zwischen .NET Framework und .NET (Core und später), authentifizierende Proxys (407), TLS-Inspektion und das praktische Isolationsverfahren. HttpClient-Erzeugungsmuster und Timeout-Entwurf selbst behandelt „HttpClient nicht mit using umschließen“, daher konzentriert sich dieser Artikel auf Proxyauflösung.

1. Zuerst das Fazit

  • Windows-Proxyeinstellungen sind nicht eine Sache; es gibt mindestens drei Familien. (1) Benutzerspezifische WinINET-Einstellungen (die Seite „Proxy“ in der Einstellungen-App = die alten Interneteinstellungen), (2) WinHTTP-Rechnereinstellungen (netsh winhttp) und (3) die Umgebungsvariablen HTTP_PROXY / HTTPS_PROXY. Welche gelesen wird, entscheidet die App-Seite.12
  • Der „Proxy“, den Sie in der Einstellungen-App sehen, sind die benutzerspezifischen Einstellungen von WinINET. Browser und interaktive Apps lesen sie; Windows-Dienste nicht. WinINET ist für die Verwendung in einem Dienst nicht unterstützt; Dienstverwendung ist die Aufgabe von WinHTTP.13
  • Die häufigste Ursache von „von Hand funktioniert es, als Dienst nicht“ ist ein Unterschied des Ausführungskontos. LocalSystem und ein Dienstkonto können den benutzerspezifischen Proxy nicht sehen, den ein Administrator auf seinem eigenen Bildschirm konfiguriert hat.34
  • netsh winhttp set proxy ist eine statische Einstellung; sie behandelt weder PAC noch automatische Erkennung noch Proxyauthentifizierung. Wenn Sie PAC oder WPAD pro Rechner konfigurieren wollen, brauchen Sie die Seite netsh winhttp set advproxy.42
  • PAC-Ergebnisse ändern sich pro URL. Die Funktion FindProxyForURL der PAC-Datei nimmt eine URL und einen Host und gibt eine Proxy-Liste oder eine direkte Verbindung (DIRECT) zurück. „Diese Site funktioniert, aber nur diese API nicht“ kann ein PAC-Zweig sein.56
  • HttpClient unter .NET (Core und später) initialisiert den Standardproxy in der Reihenfolge Umgebungsvariablen → Windows-Benutzer-Proxyeinstellungen. Wenn eine von HTTP_PROXY, HTTPS_PROXY oder ALL_PROXY definiert ist, hat sie Vorrang vor den OS-Einstellungen, sodass der Unfall „jemand hat eine Umgebungsvariable liegenlassen“ passieren kann.7
  • Der Standard von .NET Framework sind die Interneteinstellungen des Ausführungskontos, und Sie können ihn mit defaultProxy in app.config überschreiben. Einstellungen der Konfigurationsdatei haben Vorrang vor Systemeinstellungen.89
  • 407 ist ein Proxy-Authentifizierungsfehler; das ist etwas anderes als 401 (Serverauthentifizierung). Schemata umfassen Negotiate, NTLM und Basic, und in .NET übergeben Sie Anmeldeinformationen mit DefaultProxyCredentials oder WebProxy.UseDefaultCredentials. Achten Sie darauf, dass unter einem Dienstkonto der Inhalt der „Standardanmeldeinformationen“ wechselt.101112
  • Ein TLS-Inspektionsproxy hält nur als Satz mit der Verteilung des internen CA-Zertifikats zusammen. Rechner und Runtimes, die es nicht erhalten haben, bekommen einen Zertifikatsprüfungsfehler. Lösen Sie ihn durch Verteilung an den Zertifikatspeicher, nicht durch Deaktivieren der Prüfung in der App.134

In einem Satz: wann immer Sie sagen „ich habe die Proxyeinstellungen geprüft“, müssen Sie immer sagen können, welche der drei Familien Sie geprüft haben und von welchem Konto aus — das ist das Thema dieses Artikels.

2. Windows hat drei Familien von „Proxyeinstellungen“

Zuerst die Gesamtkarte. Die Pfade, die eine Windows-App nutzt, um einen Unternehmensproxy zu finden, fallen in diese drei Familien.

Einstellungsfamilie Wo Sie sie setzen / der Befehl Geltungsbereich Was sie vor allem liest
(1) WinINET (Interneteinstellungen) Einstellungen → Netzwerk und Internet → Proxy, inetcpl.cpl Pro Benutzer (Standard) Browser, interaktive Desktop-Apps, .NET-Framework-Standard
(2) WinHTTP (Rechnereinstellungen) netsh winhttp set proxy / set advproxy Rechner Windows-Dienste, einige OS-Komponenten
(3) Umgebungsvariablen HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY Prozess (vererbt je nach Definitionsort) HttpClient unter .NET (Core und später), curl, plattformübergreifende Tools wie Node.js und Python

(1) ist das, was Leute allgemein als „die Windows-Proxyeinstellungen“ erkennen; die Substanz ist WinINET-Konfiguration. Historisch sind es die Interneteinstellungen von Internet Explorer, und standardmäßig werden sie pro Benutzer gespeichert.4

(2) ist der rechnerweite Standard für Kontexte wie einen Dienst, in denen „kein angemeldeter Benutzer da ist“. (3) ist vor allem die Konvention von Tools aus der plattformübergreifenden Welt; unter Windows lesen sie auch .NET (Core und später) und curl und Ähnliche.7

Der wichtige Punkt ist, dass welche Familie gelesen wird, auf der App-Seite entschieden wird, nicht auf der Einstellungsseite. Wenn die App intern WinINET verwendet, liest sie (1); wenn WinHTTP, (2) (oder eine app-spezifische Überschreibung); wenn .NET (Core und später), (3) dann (1). Es ist also gewöhnlich nicht „die Proxyeinstellungen sind korrekt, aber es verbindet trotzdem nicht“; die Wirklichkeit ist „die Familie, die die App liest, war eine andere Familie als die, die Sie geprüft haben“.

Drei Familien von Windows-ProxyeinstellungenWinINET sind benutzerspezifische Einstellungen und Interneteinstellungen, WinHTTP der Rechnerstandard über netsh, und Umgebungsvariablen sind prozessbezogen. Welche Familie gelesen wird, entscheidet die App, nicht die EinstellungsseiteWelche Familie?WinINET benutzerspezifischWinHTTP RechnereinstellungenHTTP_PROXY und VerwandteBrowser und Desktop-AppsDienste und Teile des OS.NET Core+ und curl

Abbildung 1: Drei Familien stehen nebeneinander. Die App wählt, welche sie liest.

Wenn Sie die Gruppenrichtlinie „Proxyeinstellungen rechnerweit machen (statt benutzerspezifisch)“ aktivieren, können Sie (1) auf rechnerweit umschalten und dieselben Einstellungen auf jeden Benutzer anwenden. Mit MDM (Intune und Ähnliches) können Sie es pro Gerät mit dem NetworkProxy-CSP konfigurieren.4

3. WinINET und WinHTTP — für interaktive Apps und für Dienste

3.1. Der Unterschied der Rollen

WinINET und WinHTTP sind beide inbox-HTTP-Clientstapel von Windows, aber sie nehmen unterschiedliche Verwendungen an.

  • WinINET: Zielgruppe interaktive Desktop-Apps. Es erbt automatisch die Interneteinstellungen des Benutzers (Proxy, Cookies, Anmeldeinformationscache) und kann bei Bedarf sogar eine Eingabeoberfläche für Anmeldeinformationen zeigen. Die Verwendung in einem Dienst oder einem dienstähnlichen Prozess ist nicht unterstützt.1
  • WinHTTP: Zielgruppe Dienste und die Serverseite. Es unterstützt das Laufen unter einem Dienstkonto, Thread-Identitätswechsel und Sitzungsisolation; im Gegenzug teilt es weder die Browsereinstellungen des Benutzers noch Cookies noch Anmeldeinformationen. Es zeigt auch keine Oberfläche.3

Microsofts eigene Anleitung ist ebenso klar: „verwenden Sie WinINET, außer Sie laufen innerhalb eines Dienstes oder in einem dienstähnlichen Prozess, der Sitzungsisolation und Identitätswechsel braucht“ — andersherum gesagt, wenn es ein Dienst ist, verwenden Sie WinHTTP.1

WinINET für interaktive Apps, WinHTTP für DiensteWinINET erbt die Interneteinstellungen des angemeldeten Benutzers und ist in einem Dienst nicht unterstützt. WinHTTP läuft unter einem Dienstkonto ohne Oberfläche und teilt die Browsereinstellungen des Benutzers nichtJaDienst oder dienstähnlichInteraktive Desktop-App?WinINETWinHTTPLiest Interneteinstellungen des BenutzersRechnereinstellungen, keine UI

Abbildung 2: Interaktive Apps verwenden WinINET. Ein Dienst verwendet WinHTTP.

3.2. Grundlegende netsh-winhttp-Operationen

Der rechnerweite Standardproxy von WinHTTP wird mit netsh betrieben.2

:: Display the current WinHTTP proxy settings
netsh winhttp show proxy

:: Set a static proxy (with a bypass list)
netsh winhttp set proxy proxy-server="proxy.example.co.jp:8080" bypass-list="*.example.co.jp;<local>"

:: Import the Internet Options (WinINET) settings
netsh winhttp import proxy source=ie

:: Return to the default (DIRECT)
netsh winhttp reset proxy

Zwei Einschränkungen, die Sie hier im Kopf behalten.

  1. netsh winhttp set proxy ist eine statische Einstellung. Sie behandelt weder Proxy-Autoerkennung noch das Angeben einer PAC-URL noch Proxyauthentifizierung.4
  2. import proxy source=ie kopiert nur die statischen Einstellungen in jenem Moment; es folgt späteren Änderungen auf der Seite der Interneteinstellungen nicht. Wenn Sie eine rechnerweite Konfiguration brauchen, die PAC oder Autoerkennung einschließt, konfigurieren Sie die detaillierten Einstellungen in JSON-Form (Proxy, ProxyBypass, AutoconfigUrl, AutoDetect) mit netsh winhttp set advproxy.2

3.3. Der häufigste Fallstrick: Ein Dienst liest die IE-Einstellungen des Benutzers nicht

Das Muster, das Sie vor Ort am häufigsten sehen, sieht in zeitlicher Reihenfolge so aus.

  1. Ein Entwickler führt das Tool auf seinem eigenen PC aus → seine benutzerspezifischen Proxyeinstellungen (1) greifen und es funktioniert
  2. In der Produktion bleibt es als Windows-Dienst (Windows-Dienste erstellen und betreiben) unter LocalSystem resident
  3. Die von LocalSystem sichtbaren Einstellungen sind etwas anderes (benutzerspezifische Einstellungen sind unsichtbar, und die WinHTTP-Rechnereinstellungen sind unkonfiguriert = DIRECT) → es versucht eine direkte Verbindung zur externen API und läuft in den Timeout

Es ist nicht „es funktioniert nicht, obwohl es derselbe Rechner ist“; selbst auf demselben Rechner bedeutet ein anderes Ausführungskonto, dass ein anderer Satz Proxyeinstellungen sichtbar ist. Für einen Prozess, der kommuniziert, auch wenn kein Benutzer angemeldet ist, ist der korrekte Ansatz, rechnerweite Einstellungen in der Form vorzubereiten, die der HTTP-Stapel dieses Prozesses tatsächlich liest. Für eine native App oder eine Windows-Komponente, die WinHTTP verwendet, greifen die netsh-WinHTTP-Einstellungen.4 HttpClient unter .NET (Core und später) liest dagegen die Rechnereinstellungen von WinHTTP nicht (siehe Kapitel 5), sodass Sie für einen .NET-Dienst eine Systemumgebungsvariable (HTTPS_PROXY und Ähnliches) setzen oder HttpClientHandler.Proxy explizit aus den Appeinstellungen angeben.

Der Unfall passiert auch in die andere Richtung. Wenn Sie mit netsh winhttp set proxy einen statischen Proxy in ein Notebook backen, das zwischen Unternehmensnetz und außen wechselt, ist dieser Proxy außerhalb der Firma unerreichbar und die Kommunikation stirbt vollständig. Behandeln Sie eine rechnerstatische Einstellung als Mittel, das auf Server zielt, deren Netzwerkkonfiguration sich nicht ändert.4

Warum ein Dienst die IE-Einstellungen des Benutzers nicht siehtEin Entwicklerlauf liest benutzerspezifische WinINET-Einstellungen und funktioniert. Als LocalSystem sind diese Einstellungen unsichtbar. Eine native WinHTTP-App folgt dann unkonfigurierten Rechnereinstellungen (DIRECT). Ein .NET-Core+-Dienst verwendet weiter Umgebungsvariablen oder ein explizites handler.Proxy und wechselt nicht zu netsh winhttpWinHTTP.NET Core+Von Hand als Benutzer ausführenWinINET benutzerspezifisch greiftWindows-Dienst als LocalSystemBenutzereinstellungen unsichtbarWelcher HTTP-Stapel?WinHTTP unkonfiguriert = DIRECTUmgebungsvariablen oder handler.ProxyExterne API läuft in Timeout

Abbildung 3: Derselbe Rechner, ein anderes Konto, ein anderer sichtbarer Satz Proxyeinstellungen.

4. PAC und WPAD — was „automatische Konfiguration“ tatsächlich ist

4.1. PAC-Dateien und FindProxyForURL

Eine PAC-Datei (Proxy Auto-Configuration) ist JavaScript (ECMAScript), das berechnet, „welchen Proxy man für diese URL verwendet“, und sie enthält immer eine Funktion namens FindProxyForURL(url, host). Die Funktion gibt eine Liste von Proxys zurück, die verwendet werden sollen, oder einen besonderen Rückgabewert (DIRECT), der bedeutet, dass eine direkte Verbindung ohne Proxy in Ordnung ist.5

function FindProxyForURL(url, host) {
    // Internal domains and private addresses go direct
    if (dnsDomainIs(host, ".example.co.jp") ||
        isInNet(host, "10.0.0.0", "255.0.0.0")) {
        return "DIRECT";
    }
    // Everything else goes through a proxy. Fall back to the next if the first is unavailable
    return "PROXY proxy1.example.co.jp:8080; PROXY proxy2.example.co.jp:8080; DIRECT";
}

Zwei praktische Folgen schließen sich an.

  • Proxyauflösung muss pro URL geschehen. Weil PAC je nach URL (Host) einen anderen Proxy oder eine direkte Verbindung zurückgeben kann, ist die automatische-Proxy-Funktion von WinHTTP auch so entworfen, dass sie die Anfrage-URL jedes Mal übergibt und abfragt.6 „Der Browser sieht eine andere Site“ ist kein Beweis, dass die problematische API denselben Pfad nimmt.
  • DIRECT ist eine Anweisung, „ohne Proxy zu gehen“. Wenn Verkehr, der intern sein sollte, nie im Proxy-Log erscheint, verdächtigen Sie zuerst, dass PAC DIRECT zurückgegeben hat (oder dass es eine Bypass-Liste getroffen hat).

4.2. Automatische Erkennung über WPAD

Schalten Sie „Einstellungen automatisch erkennen“ ein, und der Rechner sucht den Ort der PAC-Datei mit dem WPAD-Protokoll (Web Proxy Auto-Discovery). In einer typischen Konfiguration gibt DHCP eine PAC-URL aus, oder DNS wird verwendet, um einen Host namens wpad nachzuschlagen, und die PAC wird von einer URL wie http://wpad/wpad.dat heruntergeladen.14

Mit anderen Worten: „automatische Erkennung“ ist keine Magie; es ist ein Mechanismus, der nur in einem Netz funktioniert, das bereits eine WPAD-Anordnung in DHCP/DNS eingerichtet hat. Automatische Erkennung allein in einem Netz ohne eine solche Anordnung fügt nur Wartezeit für einen Erkennungsfehler hinzu.

PAC löst einen Proxy pro URL auf, WPAD findet nur die PACFindProxyForURL nimmt eine URL und einen Host und gibt eine Proxy-Liste oder DIRECT zurück. WPAD lokalisiert die PAC nur über DHCP oder DNS. Ein Client, der PAC nicht auswerten kann, fällt auf einen statischen Proxy oder Umgebungsvariablen zurückProxy-ListeDIRECTAnfrage-URLFindProxyForURLÜber einen Proxy gehenOhne Proxy verbindenWPAD über DHCP oder DNSClient kann PAC nicht auswertenStatische Einstellungen oder Umgebungsvariablen

Abbildung 4: PAC entscheidet pro URL. WPAD findet nur die PAC-Datei.

4.3. Wie sich Clients verhalten, die PAC nicht auswerten können

Nicht jeder Client kann PAC auswerten.

  • Die statischen Einstellungen von netsh winhttp set proxy werten PAC nicht aus.4
  • Tools, die den Umgebungsvariablenstil HTTP_PROXY verwenden, können in der Regel nur eine feste Proxy-URL schreiben (es gibt keinen Ort, an dem man eine PAC-URL schreibt).7
  • Für eine native App, die WinHTTP direkt verwendet, hängt es davon ab, wie die Sitzung geöffnet wird. Eine App, die unter Windows 8.1 und später mit WinHttpOpen unter Angabe von WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY geöffnet wird, lässt WinHTTP die System-/Benutzer-Proxyeinstellungen (einschließlich WPAD/PAC) pro Anfrage automatisch auflösen.15 Wenn sie mit dem älteren WINHTTP_ACCESS_TYPE_DEFAULT_PROXY (ab 8.1 veraltet) oder Ähnlichem geöffnet wird, ist automatischer Proxy nicht in den HTTP-Stapel integriert, und die App muss selbst WinHttpGetProxyForUrl aufrufen und das Ergebnis auf die Anfrage anwenden. Mit anderen Worten: auf einer älteren Implementierung kann PAC vorhanden sein und trotzdem ungenutzt bleiben.5

„Der Browser geht über PAC zum richtigen Proxy, aber die Geschäftsanwendung liest PAC nicht und versucht eine direkte Verbindung und scheitert“ — das ist ein weiteres Standard-Missverhältnis. In einem PAC-betriebenen Netz müssen Sie einen Fallback entscheiden — statische Einstellungen oder Umgebungsvariablen — für Clients, die PAC nicht lesen können.

5. .NET-Proxyauflösung — Framework und Core und später sind verschiedene Dinge

Welche Proxyeinstellungen eine .NET-App liest, unterscheidet sich standardmäßig zwischen .NET Framework und .NET (Core und später). Verwechseln Sie die beiden, und Sie untersuchen eine .NET-8-App mit Framework-Ära-Wissen und verpassen es.

5.1. .NET Framework — Standard sind Interneteinstellungen, überschrieben mit defaultProxy

Unter .NET Framework verwenden HttpWebRequest und der HttpClient, der darauf sitzt, den Standardproxy, sofern Sie Proxy nicht explizit angeben. Der Standardproxy wird durch eine Kombination der Internet-Einstellungen des Systems (die WinINET-Einstellungen des Ausführungskontos) und der Konfigurationsdatei entschieden, und die Einstellungen der Konfigurationsdatei haben Vorrang.8

Sie können diesen Standard mit dem Element system.net/defaultProxy in app.config (oder machine.config) steuern.9

<configuration>
  <system.net>
    <!-- useDefaultCredentials: whether to send default credentials to an authenticating proxy -->
    <defaultProxy enabled="true" useDefaultCredentials="true">
      <proxy usesystemdefault="true"
             proxyaddress="http://proxy.example.co.jp:8080"
             bypassonlocal="true" />
      <bypasslist>
        <add address="[a-z]+\.example\.co\.jp$" />
      </bypasslist>
    </defaultProxy>
  </system.net>
</configuration>

Lassen Sie das Element defaultProxy leer, und die Systemeinstellungen (Interneteinstellungen) werden verwendet; schreiben Sie proxyaddress und Ähnliches, und jene haben Vorrang. Vom Programm aus können Sie denselben Standard mit WebRequest.DefaultWebProxy ersetzen.98

Der Fallstrick aus Kapitel 3.3 gilt hier ebenfalls. Weil der Standard „die Interneteinstellungen des Ausführungskontos“ ist, liest eine .NET-Framework-App, die unter einem Dienstkonto läuft, einen anderen (gewöhnlich leeren) Satz Einstellungen als die, die auf dem Desktop des Administrators sichtbar sind.

5.2. .NET (Core und später) — zuerst Umgebungsvariablen, dann die OS-Benutzereinstellungen

HttpClient unter .NET (Core und später) hat eine statische Eigenschaft HttpClient.DefaultProxy. Sofern ein Handler keinen Proxy explizit angibt, verwendet jede HttpClient-Instanz sie. Die Initialisierungsregel unter Windows ist „Umgebungsvariablen lesen, und wenn sie nicht definiert sind, die Benutzer-Proxyeinstellungen lesen“.7

Die verwendeten Umgebungsvariablen sind die folgenden.7

Umgebungsvariable Bedeutung
HTTP_PROXY Proxy für HTTP-Anfragen
HTTPS_PROXY Proxy für HTTPS-Anfragen
ALL_PROXY Fallback, wenn die obigen undefiniert sind
NO_PROXY Kommagetrennte Liste von Hosts, die keinen Proxy verwenden sollen

Drei Dinge zu beachten.

  • Wenn eine von HTTP_PROXY, HTTPS_PROXY oder ALL_PROXY definiert ist, hat sie Vorrang vor den Proxyeinstellungen auf der OS-Seite. Nur NO_PROXY zu definieren konfiguriert keinen Proxy aus Umgebungsvariablen, und unter Windows werden weiter die OS-Benutzer-Proxyeinstellungen verwendet. „Unsichtbare Einstellungen“ wie das Liegenlassen von HTTPS_PROXY als Systemumgebungsvariable nach einem alten Experiment oder ein CI/CD-Template, das sie injiziert, sind ein Nährboden für Unfälle.
  • NO_PROXY unterstützt keine Platzhalter (*). Um eine Subdomain zu treffen, setzen Sie einen führenden Punkt (.example.com trifft www.example.com, aber nicht example.com selbst).7
  • Außerhalb von Windows (Linux-Container und Ähnliches) wird, wenn die Umgebungsvariablen undefiniert sind, ohne Proxy initialisiert. Das Standardverhalten derselben App, das zwischen Windows und Linux wechselt, ist etwas, das Sie bei einer Containermigration bestätigen sollten.7

5.3. Explizite Angabe — HttpClientHandler.Proxy und UseProxy

Auf beiden Runtimes ist die höchste Priorität eine explizite Angabe auf dem Handler. Das Angeben von HttpClientHandler.Proxy hat Vorrang vor OS-Einstellungen und der Konfigurationsdatei, und UseProxy = false verwendet überhaupt keinen Proxy.14

using System.Net;

// Use a proxy read from app settings explicitly
var handler = new HttpClientHandler
{
    Proxy = new WebProxy("http://proxy.example.co.jp:8080")
    {
        BypassProxyOnLocal = true,
        BypassList = new[] { @"^intra\.example\.co\.jp$" },
        UseDefaultCredentials = true // On an authenticating proxy, respond with the running account's credentials
    },
    UseProxy = true
};
var client = new HttpClient(handler);

// A client that never uses a proxy (for direct internal APIs)
var directHandler = new HttpClientHandler { UseProxy = false };
var directClient = new HttpClient(directHandler);

Wenn es keine explizite Angabe gibt und den OS-Einstellungen gefolgt wird, hat das automatische Umgehen lokaler Ziele Regeln. Ein flacher Name ohne Punkt, eine Loopback-Adresse, ein Ziel, das dem eigenen Domänensuffix des Rechners entspricht, und Ähnliches können als „lokal“ behandelt werden.14 Phänomene wie „das Verhalten ändert sich, wenn ich eine IP-Adresse angebe“ oder „es ging plötzlich über den Proxy, als ich einen FQDN verwendet habe“ können von diesem Urteil verursacht werden.

Die Prioritätsreihenfolge ist wie folgt.

Priorität (hoch → niedrig) .NET Framework .NET (Core und später)
1 Explizite Angabe wie HttpClientHandler.Proxy Gleich
2 defaultProxy in app.config Zuweisung an HttpClient.DefaultProxy
3 Interneteinstellungen des Ausführungskontos Umgebungsvariablen (HTTP_PROXY und andere)
4 Windows-Benutzer-Proxyeinstellungen
Standard-Proxyauflösung in Framework versus Core und späterEin explizites HttpClientHandler.Proxy gewinnt immer. Framework verwendet dann app.config defaultProxy und die Interneteinstellungen des Ausführungskontos. Core und später verwendet eine Zuweisung an HttpClient.DefaultProxy, dann Umgebungsvariablen, dann Windows-Benutzer-ProxyeinstellungenFrameworkCore und späterExplizites handler.ProxyDieser Proxy wird verwendetKein explizites ProxyWelche Runtime?app.config defaultProxyInterneteinstellungen des KontosHttpClient.DefaultProxyHTTP_PROXY und VerwandteWindows-Benutzer-Proxyeinstellungen

Abbildung 5: Explizite Angabe gewinnt immer. Der Standardpfad unterscheidet sich nach Runtime.

6. Authentifizierende Proxys — 407 ist der Authentifizierungsfehler des Proxys

6.1. Verwechseln Sie 407 nicht mit 401

Wenn Sie versuchen, durch einen Proxy zu gehen, der Authentifizierung verlangt, gibt der Proxy den Statuscode 407 (Proxy Authentication Required) und einen Header Proxy-Authenticate zurück, der die verfügbaren Schemata auflistet. Das ist etwas anderes als die Authentifizierungsforderung des Zielservers (401 und WWW-Authenticate); die Partei, der Sie Anmeldeinformationen übergeben, und der Ort, an dem Sie sie konfigurieren, sind beide verschieden.10

407 ist der Proxy, 401 ist der Zielserver407 und Proxy-Authenticate kommen vom Proxy. 401 und WWW-Authenticate kommen vom Zielserver. Die Anmeldeinformationen und der Ort, an dem Sie sie konfigurieren, unterscheiden sichDer ProxyDas ZielAusgehende AnfrageWer verlangt Auth?407 + Proxy-Authenticate401 + WWW-AuthenticateDefaultProxyCredentials

Abbildung 6: 407 ist Proxyauthentifizierung. 401 ist Serverauthentifizierung.

Schemata umfassen Basic, das Benutzername und Passwort unverändert sendet, und Challenge/Response-Schemata wie Negotiate (Kerberos/NTLM). In einem Challenge/Response-Schema reist das Passwort selbst nicht übers Netz, und die Authentifizierung schließt über mehrere Austausche ab.10 Der Mechanismus, auf welches Schema es „zurückfällt“, wird ausführlicher in „NTLM und Kerberos anhand von Diagrammen erklärt“ behandelt.

6.2. Wie man in .NET Anmeldeinformationen übergibt

Wenn Sie den Standardproxy aus den OS-Einstellungen verwenden und nur die Authentifizierung durchbekommen wollen, verwenden Sie HttpClientHandler.DefaultProxyCredentials. Das sind die Anmeldeinformationen, die an diesen Standardproxy gesendet werden, wenn UseProxy = true und Proxy = null (= der Systemstandardproxy).11

using System.Net;

var handler = new HttpClientHandler
{
    UseProxy = true,   // The default. Combined with a null Proxy, this uses the system-default proxy
    Proxy = null,
    // Respond to 407 with the credentials of the running account (signed-in user or service account)
    DefaultProxyCredentials = CredentialCache.DefaultCredentials
};
var client = new HttpClient(handler);

Wenn Sie den Proxy explizit angeben, legen Sie die Anmeldeinformationen auf die Seite WebProxy. In vielen Clientszenarien ist die Empfehlung, die Standardanmeldeinformationen des angemeldeten Benutzers zu verwenden statt eines individuellen Benutzernamens und Passworts, und WebProxy.UseDefaultCredentials = true ist das.12

6.3. Das Dienstkonto-407-Problem

Das Ausführungskonto zählt hier ebenfalls. „Standardanmeldeinformationen“ bedeutet die Anmeldeinformationen des Kontos, das diesen Prozess ausführt. Führen Sie es als interaktiven Benutzer aus, und die Authentifizierung gegenüber dem Proxy ist als dieser Benutzer; führen Sie es als LocalSystem-Dienst aus, und es ist als Computerkonto.

  • Wenn der Proxy Benutzer über Active Directory authentifiziert, kann er ein Computerkonto oder ein lokales Konto nicht authentifizieren, und 407 setzt fort, sobald Sie die App zum Dienst machen
  • Umgekehrt haben einige Umgebungen eine Authentifizierungsausnahme auf der Proxyseite für Dienste (nach Quell-IP oder nach Konto)

Eine 407-Untersuchung schließt also nicht allein auf „die Einstellungen der App“; sie ist ein Satz mit einer Entwurfsprüfung auf der Infrastrukturseite: kann der Proxy das Ausführungskonto authentifizieren. Für eine App, die Sie zum Dienst machen werden, sollten Sie zur Entwurfszeit eines entscheiden: sie unter einem Domänendienstkonto (gMSA und Ähnliches) laufen lassen, eine Authentifizierungsausnahme auf der Proxyseite setzen oder einen internen Relais-Proxy aufstellen, der keine Authentifizierung verlangt.

Es gibt auch einen Stil, der Anmeldeinformationen in eine Umgebungsvariable einbettet, wie HTTP_PROXY=http://user:pass@proxy:80807, aber ein Klartextpasswort ist dann in einer Umgebungsvariable (= Prozessinformation) offengelegt, sodass es für den Dauerbetrieb nicht empfohlen ist.

7. HTTPS und Proxys — CONNECT-Tunnel und TLS-Inspektion

7.1. HTTPS geht durch einen Proxy als „Tunnel“

Wenn Sie einen Proxy für HTTPS verwenden, sendet der Client dem Proxy zuerst eine Anfrage CONNECT destination-host:443, und der Proxy öffnet einen TCP-Tunnel. Bei Erfolg gibt der Proxy 200 zurück, und danach führen Client und Zielserver den TLS-Handshake innerhalb dieses Tunnels aus. Wenn der Tunnel nicht öffnet, gibt der Proxy 407 (Authentifizierung erforderlich), 502 oder Ähnliches zurück.16

In diesem Modell kann der Proxy den Inhalt des Tunnels (verschlüsseltes HTTPS) nicht lesen. Was im Proxy-Log bleibt, ist der Zielhostname und ob die Verbindung gelungen ist; der URL-Pfad ist nicht sichtbar — das ist das Verhalten eines „Pass-through“-Proxys.

HTTPS durch einen Proxy ist ein CONNECT-TunnelDer Client sendet CONNECT an den Proxy, der Proxy öffnet einen TCP-Tunnel und gibt 200 zurück, dann führen Client und Ziel den TLS-Handshake im Tunnel aus. Das Proxy-Log sieht den Host, nicht den URL-PfadCONNECT host:443200 und ein TCP-TunnelTLS im TunnelClientProxyZielLog: nur Host und Erfolg

Abbildung 7: Ein Pass-through-Proxy sieht den Host, nicht den verschlüsselten Pfad.

7.2. TLS-Inspektionsproxys und Zertifikatsfehler

Sicherheitsprodukt-Proxys umfassen andererseits einen Typ TLS-Inspektion (SSL-Entschlüsselung, break and inspect), der TLS beendet, den Inhalt prüft und vor dem Weiterleiten neu verschlüsselt. In diesem Schema ist das dem Client präsentierte Serverzertifikat nicht das echte; es wird durch ein von der eigenen CA des Proxys neu signiertes Zertifikat ersetzt.13

Die Prämisse, die diese Konfiguration hält, ist daher „das CA-Zertifikat des Proxys ist an die vertrauenswürdigen Stammzertifikate jedes Clients verteilt worden“. Auf einem Rechner, der es nicht erhalten hat, oder in einer Runtime, die den Windows-Zertifikatspeicher nicht ansieht (Tools mit eigenem Vertrauensspeicher), bekommen Sie einen Zertifikatsprüfungsfehler. In .NET tritt er typischerweise als HttpRequestException auf, die eine AuthenticationException umhüllt (eine Meldung der Art „the remote certificate is invalid“).

Die Prinzipien der Korrektur sind wie folgt.

  • Verteilen Sie das interne CA-Zertifikat an den Speicher „Vertrauenswürdige Stammzertifizierungsstellen“ des lokalen Computers. Die Trennung zwischen Benutzerspeicher und Computerspeicher behandelt „Windows-Zertifikatspeicher in der Praxis“.
  • Deaktivieren Sie die Zertifikatsprüfung nicht im Code. Ein Workaround, der von ServerCertificateCustomValidationCallback immer true zurückgibt, wird zu einer verwundbaren App, die einen Man-in-the-Middle nicht erkennen kann, sobald sie in ein externes Netz geht.
  • Zertifikats-gepinnter Verkehr kann von vornherein nicht inspiziert werden. Verbindungen, die ein bestimmtes Microsoft-Zertifikat prüfen, wie einige Windows-Komponenten es tun, scheitern in dem Moment, in dem der Proxy das Zertifikat tauscht, und es gibt keinen anderen Workaround als eine Ausnahme.4 Für Verkehr, der für SaaS wie Microsoft 365 bestimmt ist, empfiehlt Microsoft selbst, ihn von Entschlüsselung und Inspektion auf Netzwerkschicht auszunehmen.13

Ein Symptom „jede interne Site ist sichtbar, aber nur ein bestimmter Clouddienst erzeugt in der App einen Zertifikatsfehler“ sollte Sie zuerst die Kombination aus TLS-Inspektions-Ausnahmeliste und Pinning verdächtigen lassen.

Ein TLS-Inspektionsproxy signiert das Zertifikat neuDer Proxy beendet TLS, prüft den Inhalt und präsentiert ein von seiner eigenen CA neu signiertes Zertifikat. Die Prüfung hält nur, wenn diese CA in den vertrauenswürdigen Stammzertifikaten liegt. Deaktivieren Sie die Prüfung nicht im CodeCA in StammzertifikatenCA fehltEchtes ServerzertifikatTLS-InspektionsproxyVon der Proxy-CA neu signiertClientprüfungErfolgZertifikatsfehlerCA an den Speicher verteilen

Abbildung 8: Inspektion funktioniert nur als Satz mit dem Verteilen der internen CA.

8. Das Isolationsverfahren — fünf Schritte, um den Schuldigen zu identifizieren

Untersuchen Sie „kann nicht verbinden“ mechanisch in dieser Reihenfolge.

Schritt Was Sie tun Was Sie lernen
(1) Reproduzieren Die problematische URL mit curl.exe -v oder Invoke-WebRequest aufrufen (möglichst auf demselben Rechner, unter demselben Konto) Ob es ein app-spezifisches Problem oder ein Umgebungsproblem ist
(2) Einstellungen sammeln Die drei Familien sammeln: netsh winhttp show proxy, die benutzerspezifischen Einstellungen und Umgebungsvariablen Was in welcher Familie liegt
(3) Das Konto identifizieren Das Ausführungskonto der Ziel-App identifizieren (ein Dienst, Aufgabenplanung, ein anderer Benutzer) Unter welchen Einstellungen und welchen Anmeldeinformationen sie läuft
(4) Den Fehler klassifizieren 407 / 403 / Namensauflösungsfehler / Timeout / Zertifikatsfehler unterscheiden Proxyauthentifizierung, Richtlinienablehnung, Pfad und TLS-Inspektion isolieren
(5) Proxy-Log Die passende Zeit im Zugriffsprotokoll des Proxy-Servers prüfen Ob es den Proxy überhaupt erreicht hat und als wen es authentifiziert hat

Sie können (2) in einem Rutsch mit PowerShell sammeln.

# (1) Per-user (WinINET) settings — note that this reads HKCU of the running account
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' |
    Select-Object ProxyEnable, ProxyServer, ProxyOverride, AutoConfigURL

# (2) Machine (WinHTTP) settings
netsh winhttp show proxy

# (3) Environment variables
Get-ChildItem env: | Where-Object Name -match 'proxy'

Einige praktische Tipps.

  • Im Reproduktionstest von (1) seien Sie sich bewusst, welche Einstellungsfamilie das Tool liest. Das Windows-inbox-curl.exe kann einen Proxy explizit mit -x http://proxy:8080 angeben, und für die TLS-Prüfung verwendet es gewöhnlich den OS-Zertifikatspeicher (Schannel). Invoke-WebRequest von Windows PowerShell 5.1 folgt der .NET-Framework-Seite (standardmäßig Interneteinstellungen); PowerShell 7 folgt der .NET-Seite (zuerst Umgebungsvariablen). „curl funktioniert, die App nicht“ ist selbst ein Hinweis auf ein Missverhältnis zwischen Konfigurationsfamilien.
  • Wenn das Ziel in (3) ein Dienst ist, prüfen Sie (1) und (2) unter demselben Konto wie der Dienst erneut. Eine Prüfung in der eigenen Sitzung des Administrators ist kein Beweis dafür, was LocalSystem sieht.
  • In der Fehlerklassifikation von (4) nehmen Sie Kapitel 6 (Authentifizierung) als ersten Kandidaten für 407, Kapitel 7 (TLS-Inspektion) für einen Zertifikatsfehler und „es erreicht den Proxy nicht“ (Pfad, Namensauflösung, Firewall) für einen Timeout. Das Muster, bei dem die Ursache eine eingehende Windows-Firewall-Regel statt des Proxys ist, behandelt „Windows-Firewall und Business-Anwendungen“.
  • Wenn Sie bis (5) kommen und im Proxy-Log immer noch keine Spur ist, hat der Verkehr den Proxy nie erreicht. Verdächtigen Sie die DIRECT-Entscheidung von PAC, eine Bypass-Liste oder eine liegengebliebene Umgebungsvariable, und bestätigen Sie bei Bedarf das tatsächliche Ziel mit einer Paketerfassung („Paketaufnahme unter Windows in der Praxis — die Wahl zwischen pktmon, netsh trace und Wireshark“).
Fünf Schritte, um einen Proxyfehler zu isolierenUnter demselben Konto reproduzieren, die drei Familien von Einstellungen sammeln, das Ausführungskonto identifizieren, den Fehler klassifizieren, dann das Proxy-Log prüfenMit curl reproduzierenDrei Familien sammelnDas Konto identifizierenDen Fehler klassifizierenDas Proxy-Log prüfen407: AuthentifizierungZertifikatsfehler: InspektionTimeout: nie erreicht

Abbildung 9: Gehen Sie die fünf Schritte der Reihe nach. Die Fehlerklasse wählt das nächste Kapitel.

9. Eine Entwurfsempfehlung — machen Sie die App zu einer, auf der Sie „den Proxy konfigurieren können“

Drehen Sie das Untersuchungsverfahren um, und es wird zu einer Entwurfsleitlinie auf der App-Seite. Für eine Windows-App, die Sie in eine Umgebung mit Unternehmensproxy liefern werden, ist Folgendes empfohlen.

  1. Machen Sie den Proxy aus den Appeinstellungen konfigurierbar. Der Standard ist „den OS-Einstellungen folgen“. In den meisten Umgebungen reicht der Standard; nur in den Ausnahmeumgebungen — PAC kann nicht gelesen werden, es läuft als Dienst, eine besondere Proxykonfiguration — machen Sie es möglich, eine Proxy-URL, eine Bypass-Liste und „keinen Proxy verwenden“ aus einer Einstellungsdatei anzugeben. HttpClientHandler.Proxy / UseProxy in Abschnitt 5.3 ist der Implementierungspunkt.14
  2. Schreiben Sie auf, wie interne Ziele (APIs, Datenbanken, Lizenzserver und Ähnliches) als Proxyausnahmen behandelt werden. Legen Sie in einer Form, die Sie in das Bereitstellungsverfahren schreiben können, fest, ob sie durch PAC DIRECT, eine Bypass-Liste oder NO_PROXY ausgenommen sind. Die Abgleichregeln von NO_PROXY (keine Platzhalter, was ein führender Punkt bedeutet) werden weit missverstanden, daher hängen Sie Beispiele an.7
  3. Entwerfen Sie Timeouts und Wiederholungen unter der Annahme, durch einen Proxy zu gehen. Wenn der Proxy down ist oder an der Authentifizierung feststeckt, friert eine Implementierung, die auf einem langen Standardtimeout wartet, sowohl die Oberfläche als auch den Betrieb. Trennen Sie einen kürzeren Verbindungs-Timeout und begrenzen Sie Wiederholungen auf idempotente Anfragen (Entwurfsdetails in „HttpClient nicht mit using umschließen“).
  4. Protokollieren Sie „welcher Proxy verwendet wurde“. Machen Sie die App selbst fähig, die erste Frage einer Fehleruntersuchung zu beantworten.

Ein Log wie in (4) ist bereits wirksam, wenn es nur das Auflösungsergebnis aufzeichnet. Der Punkt ist, den Pfad aus den Einstellungen (dem Handler) abzuleiten, die Sie tatsächlich verwendet haben, um den Client zu konfigurieren. Wenn Sie HttpClient.DefaultProxy direkt protokollieren, zeichnen Sie einen Wert auf, der vom tatsächlichen Pfad abweicht, wenn der Handler Proxy explizit angibt oder UseProxy = false setzt.

using System.Net.Http;

// handler is the same instance used to create the HttpClient
// UseProxy=false is always direct. An explicit specification wins; otherwise DefaultProxy is used
var effectiveProxy = handler.UseProxy
    ? handler.Proxy ?? HttpClient.DefaultProxy
    : null;
var target = new Uri("https://api.example.com/v1/orders");
var route = effectiveProxy is null || effectiveProxy.IsBypassed(target)
    ? "DIRECT"
    : effectiveProxy.GetProxy(target)?.ToString() ?? "DIRECT";
logger.LogInformation("HTTP send {Target} route {Route} account {User}",
    target, route, Environment.UserName);

Wenn Sie beim Start einmal „Pfad“ und „Ausführungskonto“ für die Hauptziele aufzeichnen, sind die Schritte (1) bis (3) von Kapitel 8 erledigt, indem Sie nur das Log lesen. Wenn man Ihnen sagt „es funktioniert im Browser, aber …“, von der App-Seite sagen zu können „ich habe diese Einstellung verwendet, und diesen Pfad“ ist die Bedingung einer App, die gegen Proxyärger stark ist.

Den Proxy konfigurierbar machen und den Pfad protokollierenStandardmäßig den OS-Einstellungen folgen, eine explizite Proxy-URL oder Bypass oder keinen Proxy aus Appeinstellungen erlauben und die tatsächlich verwendete Route zusammen mit dem Ausführungskonto protokollierenPAC ungelesen / Dienst / besondersGewöhnlicher FallStandard: OS-Einstellungen folgenAusnahmeumgebung?URL, Bypass oder keinen Proxy setzenOS-Standard verwendenRoute und Konto protokollieren

Abbildung 10: Konfigurieren Sie, wenn Sie müssen. Protokollieren Sie immer, welcher Pfad verwendet wurde.

10. Zusammenfassung

  • Windows-Proxyeinstellungen teilen sich in drei Familien — benutzerspezifische WinINET-Einstellungen, WinHTTP-Rechnereinstellungen und Umgebungsvariablen — und welche gelesen wird, entscheiden die App (ihr HTTP-Stapel) und das Ausführungskonto.
  • WinINET ist für interaktive Apps und für die Verwendung in einem Dienst nicht unterstützt; Dienstverwendung ist die Aufgabe von WinHTTP (netsh winhttp). Bei „von Hand funktioniert es, als Dienst nicht“ verdächtigen Sie zuerst einen Unterschied des Ausführungskontos.
  • netsh winhttp set proxy ist eine statische Einstellung und behandelt weder PAC noch automatische Erkennung noch Authentifizierung. In einem PAC-betriebenen Netz müssen Sie entscheiden, wie Clients behandelt werden, die PAC nicht lesen können.
  • FindProxyForURL von PAC gibt pro URL einen Proxy oder DIRECT zurück. WPAD funktioniert nur in einem Netz, das eine DHCP/DNS-Anordnung hat.
  • Der Standard von .NET Framework sind die Interneteinstellungen des Ausführungskontos (überschreibbar mit defaultProxy); .NET (Core und später) sind Umgebungsvariablen, dann Benutzer-Proxyeinstellungen. Eine explizite Angabe (HttpClientHandler.Proxy) hat immer die höchste Priorität.
  • 407 ist ein Proxy-Authentifizierungsfehler; in einer App, die unter einem Dienstkonto läuft, ist die typische Ursache, dass die „Standardanmeldeinformationen“ eine andere Person werden.
  • Ein TLS-Inspektionsproxy setzt die Verteilung des internen CA-Zertifikats voraus, und die korrekte Antwort auf einen Zertifikatsfehler ist Verteilung an den Zertifikatspeicher, nicht das Deaktivieren der Prüfung. Gepinnter Verkehr braucht eine Ausnahme.
  • Isolieren Sie mechanisch in der Reihenfolge „reproduzieren → die drei Familien von Einstellungen sammeln → das Ausführungskonto identifizieren → den Fehler klassifizieren → Proxy-Log“. Auf der App-Seite ist ein Entwurf, der „den Proxy konfigurieren kann und den Pfad protokolliert, den er verwendet hat“, die beste Vorbeugung.

Wenn Sie das nächste Mal mit „nur die Geschäftsanwendung kann nicht verbinden“ konsultiert werden, fragen Sie zuerst dies.

Unter wessen Konto läuft diese App, und welche der drei Familien von Proxyeinstellungen liest sie?

Diese eine Frage ändert den Eingang der Untersuchung erheblich.

Verwandte Artikel

Verwandte Beratungsbereiche

KomuraSoft LLC übernimmt die Untersuchung von Kommunikationsstörungen von Windows-Apps in Umgebungen mit Unternehmensproxy, authentifizierendem Proxy und TLS-Inspektion — „auf der Entwicklungsmaschine funktioniert es, im Kundennetzwerk nicht“, „nachdem wir daraus einen Dienst gemacht haben, erreicht es die externe API nicht mehr“ — sowie Beratung zum Kommunikationsentwurf von Geschäftsanwendungen, der eine Proxyumgebung voraussetzt (Einstellungselemente, Timeouts, Log-Entwurf). Es ist in Ordnung, mit dem Ordnen der Reproduktionsschritte und der Art, Logs zu sammeln, zu beginnen.

Quellen

  1. Microsoft Learn, WinINet vs. WinHTTP. Zur Anleitung, WinINET zu verwenden, außer Sie sind in einem Dienst oder einem Prozess, der Identitätswechsel und Sitzungsisolation braucht, und zur Funktionsvergleichstabelle, die Anmeldeinformationscache, Anmeldeinformationsaufforderungen, Dienstunterstützung, Identitätswechsel, Sitzungsisolation und Ähnliches abdeckt.  2 3 4

  2. Microsoft Learn, netsh winhttp. Zur Syntax von netsh winhttp show/set/import/reset; proxy-server und bypass-list von set proxy; import proxy source=ie; und detaillierte Proxyeinstellungen in JSON-Form (Proxy, ProxyBypass, AutoconfigUrl, AutoDetect) über set advproxy.  2 3 4

  3. Microsoft Learn, About WinHTTP. Dazu, dass WinHTTP ein für Dienst- und Serverseitenverwendung entworfener HTTP-Stapel ist, der Ausführung unter einem Dienstkonto und Identitätswechsel unterstützt und weder Cookies, Cache, Anmeldeinformationen des Browsers noch die Interneteinstellungen des Benutzers teilt.  2 3

  4. Microsoft Learn, Using a proxy with Delivery Optimization. Dazu, dass netsh winhttp set proxy eine statische Einstellung ist, die weder automatische Erkennung noch eine PAC-URL noch Proxyauthentifizierung unterstützt; zur geräteweiten Proxykonfiguration für Kontexte ohne angemeldeten Benutzer (NetworkProxy-CSP, die Richtlinie „Proxyeinstellungen rechnerweit machen“); und dazu, dass zertifikats-gepinnter Verkehr unter TLS-Inspektion scheitert und eine Ausnahme braucht.  2 3 4 5 6 7 8 9 10

  5. Microsoft Learn, WinHTTP AutoProxy Support. Dazu, dass ein PAC-Skript eine Funktion FindProxyForURL(url, host) enthält, die eine Proxy-Liste pro Anfrage berechnet und eine direkte Verbindung mit einem besonderen Rückgabewert anzeigt, und dazu, dass die ältere AutoProxy-API automatischen Proxy nicht automatisch in den HTTP-Stapel integriert, sodass die App WinHttpGetProxyForUrl aufrufen muss.  2 3

  6. Microsoft Learn, WinHttpGetProxyForUrl function. Dazu, dass es eine Implementierung des WPAD-Protokolls ist, pro URL aufgerufen werden muss, weil eine PAC-Datei einen anderen Proxy pro URL zurückgeben kann, und sowohl eine explizite PAC-URL als auch automatische Erkennung aus dem Netz unterstützt.  2

  7. Microsoft Learn, HttpClient.DefaultProxy Property. Dazu, dass Windows zuerst die Umgebungsvariablen HTTP_PROXY, HTTPS_PROXY, ALL_PROXY und NO_PROXY liest und, wenn sie undefiniert sind, die Benutzer-Proxyeinstellungen; dass Linux ohne Umgebungsvariablen ohne Proxy initialisiert; dass NO_PROXY keine Platzhalter unterstützt und einen führenden-Punkt-Subdomain-Abgleich verwendet; und dass eine Proxy-URL einen Benutzernamen und ein Passwort enthalten kann.  2 3 4 5 6 7 8 9

  8. Microsoft Learn, Configuring Internet Applications. Dazu, dass das Element defaultProxy den Standardproxy unter .NET Framework definiert; dass ein HttpWebRequest ohne Proxy-Eigenschaft den Standardproxy verwendet; und dass System-Interneteinstellungen und Einstellungen der Konfigurationsdatei kombiniert werden, wobei die Seite der Konfigurationsdatei Vorrang hat.  2 3

  9. Microsoft Learn, defaultProxy element (network settings). Zu den Attributen enabled und useDefaultCredentials des Elements system.net/defaultProxy, den Kindelementen proxy, bypasslist und module, dazu, dass die Proxyeinstellungen des Systems verwendet werden, wenn das Element leer ist, und zur Konfiguration mit HttpClient.DefaultProxy bei einer Migration zu .NET 6 und später.  2 3

  10. Microsoft Learn, Authentication in WinHTTP. Dazu, dass Statuscode 407 und ein Header Proxy-Authenticate zurückgegeben werden, wenn Proxyauthentifizierung erforderlich ist (Serverauthentifizierung ist 401 und WWW-Authenticate); zum Unterschied zwischen Basic-Authentifizierung und Challenge/Response-Schemata wie Kerberos; und dazu, dass ein Challenge/Response-Schema bedeutet, dass Benutzername und Passwort nicht übers Netz reisen.  2 3

  11. Microsoft Learn, HttpClientHandler.DefaultProxyCredentials Property. Zur Eigenschaft, die die Anmeldeinformationen setzt, die zur Authentifizierung gegenüber dem Standardproxy verwendet werden, wenn UseProxy true und Proxy null ist, sodass der Systemstandardproxy verwendet wird.  2

  12. Microsoft Learn, WebProxy.Credentials Property. Dazu, dass die Eigenschaft Credentials die Anmeldeinformationen sind, die dem Proxy als Antwort auf HTTP 407 gesendet werden, und zur Empfehlung in vielen Clientszenarien, UseDefaultCredentials auf true zu setzen, sodass die Standardanmeldeinformationen des angemeldeten Benutzers verwendet werden.  2

  13. Microsoft Learn, Understanding implications when using network intermediation to decrypt or manipulate Microsoft 365 traffic at the network layer. Dazu, dass TLS-Inspektion (SSL-Entschlüsselung) eine Konfiguration ist, in der ein Proxy oder eine Firewall TLS entschlüsselt, prüft und neu verschlüsselt; dass sie Fehlfunktion und Leistungsverschlechterung in Diensten verursachen kann, die Ende-zu-Ende-TLS annehmen; und zur Empfehlung, für Microsoft 365 bestimmten Verkehr von Entschlüsselung und Inspektion auf Netzwerkschicht auszunehmen.  2 3

  14. Microsoft Learn, Make HTTP requests with the HttpClient class. Zu den zwei Konfigurationsmethoden HttpClient.DefaultProxy und HttpClientHandler.Proxy; dazu, dass eine Proxy-Angabe Vorrang vor der Konfigurationsdatei und den Einstellungen des lokalen Computers hat; zur typischen WPAD-Konfiguration, eine PAC-Datei (wpad.dat und Ähnliches) über den DNS-Namen wpad oder DHCP zu erhalten; und zum lokalen-Ziel-Bypass-Urteil nach flachem Namen, Loopback und Domänensuffix-Treffer.  2 3 4

  15. Microsoft Learn, WinHttpOpen function. Zur Bedeutung jedes dwAccessType-Werts. WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY (Windows 8.1 und später) entscheidet den Proxy automatisch aus System-/Benutzer-Proxyeinstellungen und behandelt auch Failover und Authentifizierung automatisch, und WINHTTP_ACCESS_TYPE_DEFAULT_PROXY ist ab 8.1 veraltet. 

  16. Microsoft Learn, Work with existing on-premises proxy servers. Dazu, dass ausgehendes HTTPS mit einer CONNECT-Anfrage an den Proxy hergestellt wird; dass Erfolg HTTP 200 zurückgibt; und dass Antworten wie 407 (Authentifizierung erforderlich) oder 502 anzeigen, dass der Proxy die Kommunikation nicht zulässt, sodass Sie die Isolation mit dem Team auf der Proxyseite fortsetzen sollten. 

Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.

Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.

Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.

Häufige Fragen

Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.

Der Browser verbindet, aber nur die Geschäftsanwendung kommt nicht durch den Unternehmensproxy. Warum?
Der Browser liest die benutzerspezifischen Proxyeinstellungen von WinINET, aber eine Geschäftsanwendung liest nicht unbedingt dieselben. Eine App, die als Windows-Dienst oder unter einem anderen Konto läuft, konsultiert die von diesem Konto sichtbaren Einstellungen, die Rechnereinstellungen von WinHTTP oder Umgebungsvariablen. Identifizieren Sie zuerst das Ausführungskonto und prüfen Sie die von diesem Konto sichtbaren Proxyeinstellungen sowohl mit netsh winhttp show proxy als auch in den Benutzereinstellungen. Wenn Sie mit curl.exe oder Ähnlichem unter demselben Konto auf demselben Rechner reproduzieren können, können Sie es als Missverhältnis zwischen Konfigurationsfamilien behandeln, nicht als app-spezifisches Problem.
Ich habe netsh winhttp set proxy gesetzt, aber der Verkehr der App hat sich nicht geändert. Warum?
Was netsh winhttp setzt, ist der Rechnerstandard von WinHTTP. Es betrifft weder Browser noch interaktive Apps, die WinINET lesen, noch HttpClient von .NET (Core und später), der Umgebungsvariablen bevorzugt. netsh winhttp set proxy ist außerdem eine statische Einstellung; sie behandelt weder PAC-Autokonfiguration noch automatische Erkennung noch Proxyauthentifizierung. Sie müssen zuerst bestätigen, welchen HTTP-Stapel die Ziel-App verwendet und aus welcher Konfigurationsfamilie sie den Proxy auflöst.
Welche Proxyeinstellungen liest eine .NET-App?
.NET Framework verwendet standardmäßig die Interneteinstellungen (WinINET-Äquivalent) des Ausführungskontos, und Sie können sie mit dem Element system.net/defaultProxy in app.config überschreiben. HttpClient unter .NET (Core und später) liest zuerst Umgebungsvariablen wie HTTP_PROXY, HTTPS_PROXY und NO_PROXY und fällt, wenn sie nicht definiert sind, auf die Windows-Benutzer-Proxyeinstellungen zurück. In beiden Fällen hat ein explizites HttpClientHandler.Proxy Vorrang. Die Standardauflösungsreihenfolge unterscheidet sich daher zwischen Framework und Core und später, sodass Sie das Proxyverhalten bei einer Migration neu prüfen müssen.
Was sollte ich prüfen, wenn 407 Proxy Authentication Required zurückgegeben wird?
407 ist ein Zeichen, dass der Proxy selbst Authentifizierung verlangt; das ist etwas anderes als ein Authentifizierungsfehler des Zielservers (401). Bestätigen Sie zuerst das Authentifizierungsschema, das der Proxy verlangt (Negotiate, NTLM, Basic), aus dem Header Proxy-Authenticate, und übergeben Sie in .NET Anmeldeinformationen mit HttpClientHandler.DefaultProxyCredentials oder WebProxy.UseDefaultCredentials. In einer App, die unter einem Dienstkonto läuft, werden die „Standardanmeldeinformationen“ zu denen dieses Dienstkontos, sodass der typische Vorfall ist: es funktioniert für einen interaktiven Benutzer und liefert 407, sobald Sie daraus einen Dienst machen. Prüfen Sie auch im Proxy-Log, als wen es authentifiziert hat.
Ein TLS-Inspektionsproxy erzeugt Zertifikatsfehler. Darf ich die Zertifikatsprüfung deaktivieren?
Das Deaktivieren ist nicht empfohlen. Ein TLS-Inspektionsproxy entschlüsselt den Verkehr und präsentiert dem Client dann ein von seiner eigenen CA neu signiertes Zertifikat, sodass die Prüfung fehlschlägt, wenn dieses CA-Zertifikat nicht in den vertrauenswürdigen Stammzertifikaten liegt. Die korrekte Korrektur ist, das interne CA-Zertifikat an den Windows-Zertifikatspeicher zu verteilen (gewöhnlich Vertrauenswürdige Stammzertifizierungsstellen des lokalen Computers). Das Deaktivieren der Prüfung im Code bedeutet, dass ein Man-in-the-Middle-Angriff nicht erkannt werden kann, wenn die App in einem externen Netz verwendet wird, und die Schwachstelle bleibt.

Autorenprofil

Profilseite des Artikelautors.

Go Komura

Geschäftsführer von KomuraSoft LLC

Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.

Zurück zum Blog