„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 UmgebungsvariablenHTTP_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 proxyist eine statische Einstellung; sie behandelt weder PAC noch automatische Erkennung noch Proxyauthentifizierung. Wenn Sie PAC oder WPAD pro Rechner konfigurieren wollen, brauchen Sie die Seitenetsh winhttp set advproxy.42- PAC-Ergebnisse ändern sich pro URL. Die Funktion
FindProxyForURLder 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_PROXYoderALL_PROXYdefiniert 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
defaultProxyin 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
DefaultProxyCredentialsoderWebProxy.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“.
flowchart TB
accTitle: Drei Familien von Windows-Proxyeinstellungen
accDescr: WinINET sind benutzerspezifische Einstellungen und Interneteinstellungen, WinHTTP der Rechnerstandard über netsh, und Umgebungsvariablen sind prozessbezogen. Welche Familie gelesen wird, entscheidet die App, nicht die Einstellungsseite
fam{"Welche Familie?"}
fam --> wininet["WinINET benutzerspezifisch"]
fam --> winhttp["WinHTTP Rechnereinstellungen"]
fam --> env["HTTP_PROXY und Verwandte"]
wininet -.-> r1["Browser und Desktop-Apps"]
winhttp -.-> r2["Dienste und Teile des OS"]
env -.-> r3[".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
flowchart TB
accTitle: WinINET für interaktive Apps, WinHTTP für Dienste
accDescr: WinINET 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 nicht
q{"Interaktive Desktop-App?"}
q -->|"Ja"| ie["WinINET"]
q -->|"Dienst oder dienstähnlich"| wh["WinHTTP"]
ie -.-> ieNote["Liest Interneteinstellungen des Benutzers"]
wh -.-> whNote["Rechnereinstellungen, 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.
netsh winhttp set proxyist eine statische Einstellung. Sie behandelt weder Proxy-Autoerkennung noch das Angeben einer PAC-URL noch Proxyauthentifizierung.4import proxy source=iekopiert 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) mitnetsh 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.
- Ein Entwickler führt das Tool auf seinem eigenen PC aus → seine benutzerspezifischen Proxyeinstellungen (1) greifen und es funktioniert
- In der Produktion bleibt es als Windows-Dienst (Windows-Dienste erstellen und betreiben) unter LocalSystem resident
- 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
flowchart TB
accTitle: Warum ein Dienst die IE-Einstellungen des Benutzers nicht sieht
accDescr: Ein 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 winhttp
dev["Von Hand als Benutzer ausführen"] --> ok["WinINET benutzerspezifisch greift"]
svc["Windows-Dienst als LocalSystem"] --> miss["Benutzereinstellungen unsichtbar"]
miss --> stack{"Welcher HTTP-Stapel?"}
stack -->|"WinHTTP"| direct["WinHTTP unkonfiguriert = DIRECT"]
stack -->|".NET Core+"| env["Umgebungsvariablen oder handler.Proxy"]
direct --> fail["Externe 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.
flowchart TB
accTitle: PAC löst einen Proxy pro URL auf, WPAD findet nur die PAC
accDescr: FindProxyForURL 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ück
url["Anfrage-URL"] --> pac["FindProxyForURL"]
pac -->|"Proxy-Liste"| via["Über einen Proxy gehen"]
pac -->|"DIRECT"| dir["Ohne Proxy verbinden"]
wpad["WPAD über DHCP oder DNS"] -.-> pac
nopac["Client kann PAC nicht auswerten"] -.-> fb["Statische 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 proxywerten PAC nicht aus.4 - Tools, die den Umgebungsvariablenstil
HTTP_PROXYverwenden, 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
WinHttpOpenunter Angabe vonWINHTTP_ACCESS_TYPE_AUTOMATIC_PROXYgeöffnet wird, lässt WinHTTP die System-/Benutzer-Proxyeinstellungen (einschließlich WPAD/PAC) pro Anfrage automatisch auflösen.15 Wenn sie mit dem älterenWINHTTP_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 selbstWinHttpGetProxyForUrlaufrufen 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_PROXYoderALL_PROXYdefiniert ist, hat sie Vorrang vor den Proxyeinstellungen auf der OS-Seite. NurNO_PROXYzu definieren konfiguriert keinen Proxy aus Umgebungsvariablen, und unter Windows werden weiter die OS-Benutzer-Proxyeinstellungen verwendet. „Unsichtbare Einstellungen“ wie das Liegenlassen vonHTTPS_PROXYals Systemumgebungsvariable nach einem alten Experiment oder ein CI/CD-Template, das sie injiziert, sind ein Nährboden für Unfälle. NO_PROXYunterstützt keine Platzhalter (*). Um eine Subdomain zu treffen, setzen Sie einen führenden Punkt (.example.comtrifftwww.example.com, aber nichtexample.comselbst).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 |
flowchart TB
accTitle: Standard-Proxyauflösung in Framework versus Core und später
accDescr: Ein 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-Proxyeinstellungen
expl["Explizites handler.Proxy"] --> done["Dieser Proxy wird verwendet"]
noexpl["Kein explizites Proxy"] --> fw{"Welche Runtime?"}
fw -->|"Framework"| cfg["app.config defaultProxy"]
cfg --> ie["Interneteinstellungen des Kontos"]
fw -->|"Core und später"| dp["HttpClient.DefaultProxy"]
dp --> ev["HTTP_PROXY und Verwandte"]
ev --> user["Windows-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
flowchart TB
accTitle: 407 ist der Proxy, 401 ist der Zielserver
accDescr: 407 und Proxy-Authenticate kommen vom Proxy. 401 und WWW-Authenticate kommen vom Zielserver. Die Anmeldeinformationen und der Ort, an dem Sie sie konfigurieren, unterscheiden sich
req["Ausgehende Anfrage"] --> who{"Wer verlangt Auth?"}
who -->|"Der Proxy"| e407["407 + Proxy-Authenticate"]
who -->|"Das Ziel"| e401["401 + WWW-Authenticate"]
e407 -.-> cred["DefaultProxyCredentials"]
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.
flowchart TB
accTitle: HTTPS durch einen Proxy ist ein CONNECT-Tunnel
accDescr: Der 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-Pfad
cli["Client"] -->|"CONNECT host:443"| px["Proxy"]
px -->|"200 und ein TCP-Tunnel"| dest["Ziel"]
dest -->|"TLS im Tunnel"| cli
px -.-> log["Log: 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
ServerCertificateCustomValidationCallbackimmer 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.
flowchart TB
accTitle: Ein TLS-Inspektionsproxy signiert das Zertifikat neu
accDescr: Der 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 Code
real["Echtes Serverzertifikat"] --> px["TLS-Inspektionsproxy"]
px --> fake["Von der Proxy-CA neu signiert"]
fake --> client["Clientprüfung"]
client -->|"CA in Stammzertifikaten"| ok["Erfolg"]
client -->|"CA fehlt"| err["Zertifikatsfehler"]
err -.-> fix["CA 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.exekann einen Proxy explizit mit-x http://proxy:8080angeben, und für die TLS-Prüfung verwendet es gewöhnlich den OS-Zertifikatspeicher (Schannel).Invoke-WebRequestvon 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“).
flowchart TB
accTitle: Fünf Schritte, um einen Proxyfehler zu isolieren
accDescr: Unter demselben Konto reproduzieren, die drei Familien von Einstellungen sammeln, das Ausführungskonto identifizieren, den Fehler klassifizieren, dann das Proxy-Log prüfen
s1["Mit curl reproduzieren"] --> s2["Drei Familien sammeln"]
s2 --> s3["Das Konto identifizieren"]
s3 --> s4["Den Fehler klassifizieren"]
s4 --> s5["Das Proxy-Log prüfen"]
s4 -.-> e407["407: Authentifizierung"]
s4 -.-> ecert["Zertifikatsfehler: Inspektion"]
s4 -.-> eto["Timeout: 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.
- 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/UseProxyin Abschnitt 5.3 ist der Implementierungspunkt.14 - 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_PROXYausgenommen sind. Die Abgleichregeln vonNO_PROXY(keine Platzhalter, was ein führender Punkt bedeutet) werden weit missverstanden, daher hängen Sie Beispiele an.7 - 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“).
- 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.
flowchart TB
accTitle: Den Proxy konfigurierbar machen und den Pfad protokollieren
accDescr: Standardmäß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 protokollieren
def["Standard: OS-Einstellungen folgen"] --> exc{"Ausnahmeumgebung?"}
exc -->|"PAC ungelesen / Dienst / besonders"| cfg["URL, Bypass oder keinen Proxy setzen"]
exc -->|"Gewöhnlicher Fall"| os["OS-Standard verwenden"]
cfg --> log["Route und Konto protokollieren"]
os --> log
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 proxyist 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.FindProxyForURLvon 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
- HttpClient nicht mit using umschließen ── HTTP-Kommunikation in C#-Geschäftsanwendungen (Erzeugungsmuster, Timeouts, Retries)
- Paketaufnahme unter Windows in der Praxis — die Wahl zwischen pktmon, netsh trace und Wireshark
- Windows-Firewall und Business-Anwendungen — Eingehende Regeln über das Installationsprogramm registrieren
- Windows-Dienste erstellen und betreiben ── Von der Abgrenzung zur Aufgabenplanung bis zur Umwandlung eines BackgroundService in einen Dienst
- NTLM und Kerberos anhand von Diagrammen erklärt — Warum die Authentifizierung auf NTLM zurückfällt
- Windows-Zertifikatspeicher in der Praxis — Benutzer oder Computer, wofür entscheiden Sie sich?
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.
- Windows-App-Entwicklung
- Fehleruntersuchung und Ursachenanalyse
- Technische Beratung und Design-Review
- Kontakt
Quellen
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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. ↩
-
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. ↩
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
HttpClient nicht mit using umschließen ── HTTP-Kommunikation in C#-Geschäftsanwendungen (Erzeugungsmuster, Timeouts, Retries)
Wer HttpClient in C# bei jeder Anfrage neu mit using erzeugt, riskiert eine Socket-Erschöpfung; wer ihn einfach static macht, folgt DNS-Ä...
Paketmitschnitt unter Windows in der Praxis — pktmon, netsh trace und Wireshark wählen
Ein Kommunikationsausfall, der im Anwendungslog nur „Timeout“ hinterlässt, lässt sich eine Schicht tiefer untersuchen: an den Paketen, di...
Praktische Best Practices für Multithreading: .NET-Edition — Was Sie entscheiden sollten, bevor Sie weitere Threads hinzufügen
Eine praxisnahe Übersicht der Entwurfsregeln, die verhindern, dass Multithreading-Code in .NET/C# gelegentlich abstürzt oder hängen bleib...
WMI/CIM aus C# und PowerShell verwenden — Praxisleitfaden für Hardwareinformationen, Prozessüberwachung und Remoteabfragen
WMI/CIM ist die Standardlösung, um die Seriennummer eines PCs auszulesen, freien Festplattenspeicher zu überwachen und den Start von Proz...
Windows-Firewall und Business-Anwendungen — Eingehende Regeln über das Installationsprogramm registrieren
„Auf dem Entwicklungsrechner funktioniert es, aber beim Kunden gibt es keine Verbindung“ hat fast immer dieselbe Ursache: die Windows-Fir...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
Leistungen zu diesem Thema
Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.
Windows-App-Entwicklung
Geschäftsanwendungen, Geräteintegration und Kommunikationstools von den Anforderungen bis zur Umsetzung.
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.