«Il browser apre i siti esterni, ma solo l’app aziendale non raggiunge l’API esterna.» «Funziona sulla macchina di sviluppo, ma va in timeout sulla rete del cliente.» «Comunica quando la eseguo a mano, e fallisce appena la trasformo in un servizio Windows.» — Quando fate girare un’app aziendale in un ambiente con proxy aziendale, questo tipo di consulto è tra i più comuni.
Nella maggior parte dei casi la causa non è né un’interruzione del server proxy né un bug dell’app. Windows ha diverse famiglie separate di ciò che la gente chiama «impostazioni proxy», e quali impostazioni chi legge differisce per app (per lo stack HTTP che usa) e per account di esecuzione — quel disallineamento. Le impostazioni che legge il browser, quelle che legge un servizio e quelle che legge HttpClient di .NET possono ciascuna essere una cosa diversa. Una volta che quella struttura è in testa, isolare «funziona nel browser, ma…» diventa sorprendentemente veloce.
Questo articolo è rivolto al personale IT di piccole e medie imprese e agli sviluppatori di app Windows. Collega, in un’unica immagine, le tre famiglie di impostazioni proxy — WinINET, WinHTTP e variabili d’ambiente —, l’autoconfigurazione PAC e WPAD, la differenza di risoluzione del proxy tra .NET Framework e .NET (Core e successivi), i proxy con autenticazione (407), l’ispezione TLS e la procedura pratica di isolamento. I pattern di creazione di HttpClient e la progettazione dei timeout in sé sono trattati in «Non racchiudere HttpClient in un using», quindi questo articolo si concentra sulla risoluzione del proxy.
1. Prima la conclusione
- Le impostazioni proxy di Windows non sono una cosa sola; ci sono almeno tre famiglie. (1) Impostazioni WinINET per utente (la pagina «Proxy» dell’app Impostazioni = le vecchie Opzioni Internet), (2) impostazioni macchina WinHTTP (
netsh winhttp) e (3) le variabili d’ambienteHTTP_PROXY/HTTPS_PROXY. Quale viene letta si decide sul lato app.12 - Il «Proxy» che vedete nell’app Impostazioni sono le impostazioni per utente di WinINET. I browser e le app interattive le leggono; i servizi Windows no. WinINET non è supportato per l’uso in un servizio; l’uso da servizio è il lavoro di WinHTTP.13
- La causa più comune di «funziona a mano ma non come servizio» è una differenza di account di esecuzione. LocalSystem e un account di servizio non vedono il proxy per utente che un amministratore ha configurato sul proprio schermo.34
netsh winhttp set proxyè un’impostazione statica; non gestisce PAC, rilevamento automatico né autenticazione proxy. Se volete configurare PAC o WPAD per macchina, vi serve il latonetsh winhttp set advproxy.42- I risultati PAC cambiano per URL. La funzione
FindProxyForURLdel file PAC prende un URL e un host e restituisce un elenco di proxy o una connessione diretta (DIRECT). «Quel sito funziona, ma solo questa API no» può essere un ramo PAC.56 - HttpClient su .NET (Core e successivi) inizializza il proxy predefinito nell’ordine variabili d’ambiente → impostazioni proxy utente Windows. Se una qualsiasi di
HTTP_PROXY,HTTPS_PROXYoALL_PROXYè definita, ha priorità sulle impostazioni del sistema operativo, quindi può accadere l’incidente «qualcuno ha lasciato una variabile d’ambiente».7 - Il default di .NET Framework sono le Opzioni Internet dell’account di esecuzione, e potete sovrascriverlo con
defaultProxyin app.config. Le impostazioni del file di configurazione hanno priorità su quelle di sistema.89 - 407 è un errore di autenticazione del proxy; è una cosa diversa da 401 (autenticazione del server). Gli schemi includono Negotiate, NTLM e Basic, e in .NET passate le credenziali con
DefaultProxyCredentialsoWebProxy.UseDefaultCredentials. Fate attenzione al fatto che sotto un account di servizio il contenuto delle «credenziali predefinite» cambia.101112 - Un proxy di ispezione TLS regge solo come insieme con la distribuzione del certificato CA interno. Macchine e runtime che non l’hanno ricevuto hanno un errore di convalida del certificato. Risolvetelo distribuendo all’archivio certificati, non disattivando la convalida nell’app.134
In una frase: ogni volta che dite «ho controllato le impostazioni proxy», dovete sempre poter dire quale delle tre famiglie avete controllato, e da quale account — questo è l’argomento dell’articolo.
2. Windows ha tre famiglie di «impostazioni proxy»
Prima, la mappa d’insieme. I percorsi che un’app Windows usa per trovare un proxy aziendale cadono in queste tre famiglie.
| Famiglia di impostazioni | Dove la impostate / il comando | Ambito | Chi la legge soprattutto |
|---|---|---|---|
| (1) WinINET (Opzioni Internet) | Impostazioni → Rete e Internet → Proxy, inetcpl.cpl |
Per utente (default) | Browser, app desktop interattive, default .NET Framework |
| (2) WinHTTP (impostazioni macchina) | netsh winhttp set proxy / set advproxy |
Macchina | Servizi Windows, alcuni componenti del sistema operativo |
| (3) Variabili d’ambiente | HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY |
Processo (ereditate a seconda di dove sono state definite) | HttpClient su .NET (Core e successivi), curl, strumenti multipiattaforma come Node.js e Python |
(1) è ciò che la gente riconosce in genere come «le impostazioni proxy di Windows»; la sostanza è la configurazione WinINET. Storicamente sono le Opzioni Internet di Internet Explorer, e per default sono memorizzate per utente.4
(2) è il default per macchina per contesti come un servizio in cui «non c’è un utente connesso». (3) è soprattutto la convenzione degli strumenti che arrivano dal mondo multipiattaforma; su Windows le leggono anche .NET (Core e successivi) e curl e simili.7
Il punto importante è che quale famiglia viene letta si decide sul lato app, non sul lato impostazioni. Se l’app usa WinINET internamente legge (1); se WinHTTP, (2) (o un override specifico dell’app); se .NET (Core e successivi), (3) poi (1). Quindi di solito non è «le impostazioni proxy sono corrette ma ancora non si connette»; la realtà è «la famiglia che l’app stava leggendo era una famiglia diversa da quella che avete controllato».
flowchart TB
accTitle: Tre famiglie di impostazioni proxy Windows
accDescr: WinINET sono Impostazioni e Opzioni Internet per utente, WinHTTP è il default macchina via netsh, e le variabili d'ambiente sono a ambito di processo. Quale famiglia viene letta lo decide l'app, non il lato impostazioni
fam{"Quale famiglia?"}
fam --> wininet["Impostazioni WinINET per utente"]
fam --> winhttp["Impostazioni macchina WinHTTP"]
fam --> env["HTTP_PROXY e consimili"]
wininet -.-> r1["Browser e app desktop"]
winhttp -.-> r2["Servizi e parti del sistema"]
env -.-> r3[".NET Core+ e curl"]
Figura 1: Tre famiglie stanno affiancate. L’app sceglie quale legge.
Se abilitate i Criteri di gruppo «Rendi le impostazioni proxy per macchina (anziché per utente)», potete passare (1) a per macchina e applicare le stesse impostazioni a ogni utente. Con MDM (Intune e simili) potete configurarlo per dispositivo con il CSP NetworkProxy.4
3. WinINET e WinHTTP — per le app interattive e per i servizi
3.1. La differenza di ruoli
WinINET e WinHTTP sono entrambi stack client HTTP inbox di Windows, ma assumono usi diversi.
- WinINET: rivolto alle app desktop interattive. Eredita automaticamente le Opzioni Internet dell’utente (proxy, cookie, cache delle credenziali) e può persino mostrare un’interfaccia di inserimento credenziali se serve. L’uso in un servizio o in un processo simile a un servizio non è supportato.1
- WinHTTP: rivolto ai servizi e al lato server. Supporta l’esecuzione sotto un account di servizio, l’impersonation del thread e l’isolamento di sessione; in cambio non condivide le impostazioni del browser dell’utente, i cookie o le credenziali. Non mostra nemmeno un’interfaccia.3
La guida di Microsoft stessa è altrettanto chiara: «usate WinINET a meno che non stiate eseguendo all’interno di un servizio, o in un processo simile a un servizio che ha bisogno di isolamento di sessione e impersonation» — detto all’inverso, se è un servizio, usate WinHTTP.1
flowchart TB
accTitle: WinINET per le app interattive, WinHTTP per i servizi
accDescr: WinINET eredita le Opzioni Internet dell'utente connesso e non è supportato in un servizio. WinHTTP gira sotto un account di servizio senza interfaccia e non condivide le impostazioni del browser dell'utente
q{"App desktop interattiva?"}
q -->|"Sì"| ie["WinINET"]
q -->|"Servizio o simile"| wh["WinHTTP"]
ie -.-> ieNote["Legge le Opzioni Internet dell'utente"]
wh -.-> whNote["Impostazioni macchina, nessuna UI"]
Figura 2: Le app interattive usano WinINET. Un servizio usa WinHTTP.
3.2. Operazioni di base di netsh winhttp
Il proxy predefinito macchina di WinHTTP si opera con netsh.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
Due vincoli da tenere a mente qui.
netsh winhttp set proxyè un’impostazione statica. Non gestisce né il rilevamento automatico del proxy, né la specificazione di un URL PAC, né l’autenticazione proxy.4import proxy source=iecopia solo le impostazioni statiche in quel momento; non segue i cambiamenti successivi sul lato Opzioni Internet. Quando vi serve una configurazione per macchina che include PAC o rilevamento automatico, configurate le impostazioni dettagliate in forma JSON (Proxy,ProxyBypass,AutoconfigUrl,AutoDetect) connetsh winhttp set advproxy.2
3.3. La trappola più comune: un servizio non legge le impostazioni IE dell’utente
Il pattern che vedete più spesso sul campo, in ordine temporale, è questo.
- Uno sviluppatore esegue lo strumento sul proprio PC → le sue impostazioni proxy per utente (1) hanno effetto e funziona
- In produzione viene lasciato residente come servizio Windows (Come creare e gestire un servizio Windows) sotto LocalSystem
- Le impostazioni visibili da LocalSystem sono un’altra cosa (le impostazioni per utente sono invisibili, e le impostazioni macchina WinHTTP sono non configurate = DIRECT) → tenta una connessione diretta all’API esterna e va in timeout
Non è «non funziona anche se è la stessa macchina»; anche sulla stessa macchina, un account di esecuzione diverso significa che è visibile un insieme diverso di impostazioni proxy. Per un processo che comunica anche quando nessun utente è connesso, l’approccio corretto è preparare impostazioni per macchina nella forma che lo stack HTTP di quel processo legge davvero. Per un’app nativa o un componente Windows che usa WinHTTP, le impostazioni WinHTTP di netsh hanno effetto.4 HttpClient su .NET (Core e successivi), invece, non legge le impostazioni macchina di WinHTTP (vedere il capitolo 5), quindi per un servizio .NET impostate una variabile d’ambiente di sistema (HTTPS_PROXY e simili) o specificate HttpClientHandler.Proxy in modo esplicito dalle impostazioni dell’app.
L’incidente accade anche nell’altra direzione. Se cuocete un proxy statico in un portatile che si sposta tra la rete aziendale e l’esterno con netsh winhttp set proxy, quel proxy è irraggiungibile fuori dall’azienda e la comunicazione muore del tutto. Trattate un’impostazione statica di macchina come un mezzo rivolto a server la cui configurazione di rete non cambia.4
flowchart TB
accTitle: Perché un servizio non vede le impostazioni IE dell'utente
accDescr: Un'esecuzione da sviluppatore legge le impostazioni WinINET per utente e funziona. Come LocalSystem quelle impostazioni sono invisibili. Un'app WinHTTP nativa segue allora le impostazioni macchina non configurate (DIRECT). Un servizio .NET Core+ usa ancora variabili d'ambiente o un handler.Proxy esplicito e non passa a netsh winhttp
dev["Esecuzione a mano come utente"] --> ok["Si applicano le impostazioni WinINET per utente"]
svc["Servizio Windows come LocalSystem"] --> miss["Le impostazioni per utente sono invisibili"]
miss --> stack{"Quale stack HTTP?"}
stack -->|"WinHTTP"| direct["WinHTTP non configurato = DIRECT"]
stack -->|".NET Core+"| env["Variabili d'amb. o handler.Proxy"]
direct --> fail["L'API esterna va in timeout"]
Figura 3: La stessa macchina, un account diverso, un insieme diverso di impostazioni proxy visibili.
4. PAC e WPAD — che cosa è davvero la «configurazione automatica»
4.1. File PAC e FindProxyForURL
Un file PAC (Proxy Auto-Configuration) è JavaScript (ECMAScript) che calcola «quale proxy usare per questo URL», e contiene sempre una funzione di nome FindProxyForURL(url, host). La funzione restituisce un elenco di proxy da usare, o un valore di ritorno speciale (DIRECT) che significa che va bene connettersi direttamente senza proxy.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";
}
Ne seguono due conseguenze pratiche.
- La risoluzione del proxy va fatta per URL. Poiché PAC può restituire un proxy diverso o una connessione diretta a seconda dell’URL (host), anche la funzione di proxy automatico di WinHTTP è progettata per passare l’URL della richiesta e interrogare ogni volta.6 «Il browser vede un altro sito» non è prova che l’API problematica prenda lo stesso percorso.
- DIRECT è un’istruzione di «andare senza proxy». Se il traffico che dovrebbe essere interno non compare mai nel log del proxy, sospettate prima che PAC abbia restituito DIRECT (o che abbia corrisposto a un elenco di bypass).
4.2. Rilevamento automatico via WPAD
Attivate «Rileva automaticamente le impostazioni» e la macchina cerca la posizione del file PAC con il protocollo WPAD (Web Proxy Auto-Discovery). In una configurazione tipica, DHCP consegna un URL PAC, oppure si usa DNS per cercare un host di nome wpad e il PAC viene scaricato da un URL come http://wpad/wpad.dat.14
In altre parole, il «rilevamento automatico» non è magia; è un meccanismo che funziona solo su una rete che ha già allestito un dispositivo WPAD in DHCP/DNS. Attivare da solo il rilevamento automatico su una rete senza tale dispositivo aggiunge solo tempo di attesa per un fallimento del rilevamento.
flowchart TB
accTitle: PAC risolve un proxy per URL, WPAD trova solo il PAC
accDescr: FindProxyForURL prende un URL e un host e restituisce un elenco di proxy o DIRECT. WPAD localizza il PAC solo via DHCP o DNS. Un client che non può valutare PAC ricade su un proxy statico o sulle variabili d'ambiente
url["URL della richiesta"] --> pac["FindProxyForURL"]
pac -->|"elenco di proxy"| via["Passare da un proxy"]
pac -->|"DIRECT"| dir["Connettersi senza proxy"]
wpad["WPAD via DHCP o DNS"] -.-> pac
nopac["Client che non valuta PAC"] -.-> fb["Impostazioni statiche o var. d'amb."]
Figura 4: PAC decide per URL. WPAD trova solo il file PAC.
4.3. Come si comportano i client che non possono valutare PAC
Non ogni client può valutare PAC.
- Le impostazioni statiche di
netsh winhttp set proxynon valutano PAC.4 - Gli strumenti che usano lo stile variabile d’ambiente
HTTP_PROXYpossono, di regola, scrivere solo un URL di proxy fisso (non c’è dove scrivere un URL PAC).7 - Per un’app nativa che usa WinHTTP direttamente, dipende da come viene aperta la sessione. Un’app aperta con
WinHttpOpensu Windows 8.1 e successivi specificandoWINHTTP_ACCESS_TYPE_AUTOMATIC_PROXYha WinHTTP che risolve automaticamente le impostazioni proxy di sistema/utente (incluso WPAD/PAC) per richiesta.15 Se è aperta con il più vecchioWINHTTP_ACCESS_TYPE_DEFAULT_PROXY(deprecato da 8.1 in poi) o simile, il proxy automatico non è integrato nello stack HTTP, e l’app deve chiamare da séWinHttpGetProxyForUrle applicare il risultato alla richiesta. In altre parole, su un’implementazione più vecchia, PAC può essere presente e restare inutilizzato.5
«Il browser va al proxy giusto via PAC, ma l’app aziendale non legge PAC e tenta una connessione diretta e fallisce» — questo è un altro disallineamento classico. Su una rete operata in PAC dovete decidere un fallback — impostazioni statiche o variabili d’ambiente — per i client che non possono leggere PAC.
5. Risoluzione del proxy .NET — Framework e Core e successivi sono cose diverse
Quali impostazioni proxy legge un’app .NET differisce per default tra .NET Framework e .NET (Core e successivi). Confondete i due e indagherete un’app .NET 8 con conoscenze dell’era Framework e mancherete.
5.1. .NET Framework — il default sono le Opzioni Internet, sovrascritte con defaultProxy
Su .NET Framework, HttpWebRequest e l’HttpClient che vi siede sopra usano il proxy predefinito a meno che non specifichiate Proxy in modo esplicito. Il proxy predefinito è deciso da una combinazione delle impostazioni Internet del sistema (le impostazioni WinINET dell’account di esecuzione) e del file di configurazione, e le impostazioni del file di configurazione hanno priorità.8
Potete controllare questo default con l’elemento system.net/defaultProxy in app.config (o machine.config).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>
Lasciate vuoto l’elemento defaultProxy e si usano le impostazioni di sistema (Opzioni Internet); scrivete proxyaddress e simili e quelle hanno priorità. Dal programma potete sostituire lo stesso default con WebRequest.DefaultWebProxy.98
La trappola del capitolo 3.3 vale anche qui. Poiché il default è «le Opzioni Internet dell’account di esecuzione», un’app .NET Framework che gira sotto un account di servizio legge un insieme di impostazioni diverso (di solito vuoto) da quelle visibili sul desktop dell’amministratore.
5.2. .NET (Core e successivi) — prima le variabili d’ambiente, poi le impostazioni utente del sistema operativo
HttpClient su .NET (Core e successivi) ha una proprietà statica HttpClient.DefaultProxy. A meno che un handler non specifichi un proxy in modo esplicito, ogni istanza HttpClient la usa. La regola di inizializzazione su Windows è «leggere le variabili d’ambiente e, se non sono definite, leggere le impostazioni proxy utente».7
Le variabili d’ambiente usate sono le seguenti.7
| Variabile d’ambiente | Significato |
|---|---|
HTTP_PROXY |
Proxy usato per le richieste HTTP |
HTTPS_PROXY |
Proxy usato per le richieste HTTPS |
ALL_PROXY |
Fallback quando le precedenti sono indefinite |
NO_PROXY |
Elenco separato da virgole di host che non devono usare un proxy |
Tre cose da osservare.
- Se una qualsiasi di
HTTP_PROXY,HTTPS_PROXYoALL_PROXYè definita, ha priorità sulle impostazioni proxy lato sistema operativo. Definire soloNO_PROXYnon configura un proxy dalle variabili d’ambiente, e su Windows si continuano a usare le impostazioni proxy utente del sistema operativo. «Impostazioni invisibili» come lasciareHTTPS_PROXYcome variabile d’ambiente di sistema dopo un vecchio esperimento, o un modello CI/CD che la inietta, sono un terreno di coltura per incidenti. NO_PROXYnon supporta i caratteri jolly (*). Per corrispondere a un sottodominio, mettete un punto iniziale (.example.comcorrisponde awww.example.comma non aexample.comstesso).7- Fuori da Windows (contenitori Linux e simili), se le variabili d’ambiente sono indefinite viene inizializzato senza proxy. Il comportamento predefinito della stessa app che cambia tra Windows e Linux è qualcosa da confermare al momento di una migrazione a contenitore.7
5.3. Specificazione esplicita — HttpClientHandler.Proxy e UseProxy
Su entrambi i runtime, la priorità più alta è una specificazione esplicita sull’handler. Specificare HttpClientHandler.Proxy ha priorità sulle impostazioni del sistema operativo e sul file di configurazione, e UseProxy = false non usa affatto un 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);
Quando non c’è specificazione esplicita e si seguono le impostazioni del sistema operativo, il bypass automatico delle destinazioni locali ha regole. Un nome piatto senza punto, un indirizzo di loopback, una destinazione che corrisponde al suffisso di dominio della macchina stessa e simili possono essere trattati come «locali».14 Fenomeni come «il comportamento cambia se specifico un indirizzo IP» o «ha improvvisamente iniziato a passare dal proxy quando ho usato un FQDN» possono essere causati da questo giudizio.
L’ordine di priorità è il seguente.
| Priorità (alta → bassa) | .NET Framework | .NET (Core e successivi) |
|---|---|---|
| 1 | Specificazione esplicita come HttpClientHandler.Proxy |
Uguale |
| 2 | defaultProxy in app.config |
Assegnazione a HttpClient.DefaultProxy |
| 3 | Opzioni Internet dell’account di esecuzione | Variabili d’ambiente (HTTP_PROXY e altre) |
| 4 | — | Impostazioni proxy utente Windows |
flowchart TB
accTitle: Risoluzione del proxy predefinito in Framework rispetto a Core e successivi
accDescr: Un HttpClientHandler.Proxy esplicito vince sempre. Framework usa poi app.config defaultProxy e le Opzioni Internet dell'account di esecuzione. Core e successivi usa un'assegnazione a HttpClient.DefaultProxy, poi le variabili d'ambiente, poi le impostazioni proxy utente Windows
expl["handler.Proxy esplicito"] --> done["Si usa quel proxy"]
noexpl["Nessun Proxy esplicito"] --> fw{"Quale runtime?"}
fw -->|"Framework"| cfg["app.config defaultProxy"]
cfg --> ie["Opzioni Internet dell'account"]
fw -->|"Core e successivi"| dp["HttpClient.DefaultProxy"]
dp --> ev["HTTP_PROXY e consimili"]
ev --> user["Impostazioni proxy utente Windows"]
Figura 5: La specificazione esplicita vince sempre. Il percorso predefinito differisce per runtime.
6. Proxy con autenticazione — 407 è l’errore di autenticazione del proxy
6.1. Non confondete 407 con 401
Quando tentate di passare da un proxy che chiede autenticazione, il proxy restituisce il codice di stato 407 (Proxy Authentication Required) e un’intestazione Proxy-Authenticate che elenca gli schemi disponibili. È una cosa diversa dalla richiesta di autenticazione del server di destinazione (401 e WWW-Authenticate); la parte a cui consegnate le credenziali e il posto in cui le configurate sono entrambi diversi.10
flowchart TB
accTitle: 407 è il proxy, 401 è il server di destinazione
accDescr: 407 e Proxy-Authenticate vengono dal proxy. 401 e WWW-Authenticate vengono dal server di destinazione. Le credenziali e il posto in cui le configurate differiscono
req["Richiesta in uscita"] --> who{"Chi chiede autenticazione?"}
who -->|"Il proxy"| e407["407 + Proxy-Authenticate"]
who -->|"La destinazione"| e401["401 + WWW-Authenticate"]
e407 -.-> cred["DefaultProxyCredentials"]
Figura 6: 407 è autenticazione del proxy. 401 è autenticazione del server.
Gli schemi includono Basic, che invia nome utente e password così come sono, e schemi challenge/response come Negotiate (Kerberos/NTLM). In uno schema challenge/response la password stessa non viaggia in rete, e l’autenticazione si completa in diversi scambi.10 Il meccanismo dello schema su cui «ricade» è trattato in più dettaglio in «NTLM e Kerberos spiegati con i diagrammi».
6.2. Come passare le credenziali in .NET
Quando volete usare il proxy predefinito che viene dalle impostazioni del sistema operativo e far passare solo l’autenticazione, usate HttpClientHandler.DefaultProxyCredentials. Sono le credenziali inviate a quel proxy predefinito quando UseProxy = true e Proxy = null (= il proxy predefinito di sistema).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);
Quando specificate il proxy in modo esplicito, mettete le credenziali sul lato WebProxy. In molti scenari client la raccomandazione è usare le credenziali predefinite dell’utente connesso anziché un nome utente e una password individuali, e WebProxy.UseDefaultCredentials = true è quello.12
6.3. Il problema 407 dell’account di servizio
L’account di esecuzione conta anche qui. «Credenziali predefinite» significa le credenziali dell’account che sta eseguendo quel processo. Eseguitela come utente interattivo e l’autenticazione verso il proxy è come quell’utente; eseguitela come servizio LocalSystem ed è come account computer.
- Se il proxy autentica gli utenti tramite Active Directory, non può autenticare un account computer o un account locale, e 407 continua appena trasformate l’app in servizio
- Al contrario, alcuni ambienti hanno un’esenzione di autenticazione sul lato proxy per i servizi (per IP di origine o per account)
Quindi un’indagine 407 non si chiude sulle sole «impostazioni dell’app»; è un insieme con un controllo di progettazione sul lato infrastruttura: il proxy può autenticare l’account di esecuzione. Per un’app che trasformerete in servizio, dovreste decidere in fase di progettazione uno tra: farla girare sotto un account di servizio di dominio (gMSA e simili), mettere un’esenzione di autenticazione sul lato proxy, o alzare un proxy di relè interno che non richiede autenticazione.
C’è anche uno stile che incorpora le credenziali in una variabile d’ambiente, come HTTP_PROXY=http://user:pass@proxy:80807, ma allora una password in chiaro è esposta in una variabile d’ambiente (= informazione di processo), quindi non è raccomandato per un’esercizio permanente.
7. HTTPS e i proxy — tunnel CONNECT e ispezione TLS
7.1. HTTPS passa da un proxy come un «tunnel»
Quando usate un proxy per HTTPS, il client invia prima al proxy una richiesta CONNECT destination-host:443, e il proxy apre un tunnel TCP. In caso di successo il proxy restituisce 200, e dopo il client e il server di destinazione eseguono l’handshake TLS dentro quel tunnel. Se il tunnel non si apre, il proxy restituisce 407 (autenticazione richiesta), 502 o simile.16
In questo modello il proxy non può leggere il contenuto del tunnel (HTTPS cifrato). Ciò che resta nel log del proxy è il nome host di destinazione e se la connessione è riuscita; il percorso URL non è visibile — quello è il comportamento di un proxy «pass-through».
flowchart TB
accTitle: HTTPS attraverso un proxy è un tunnel CONNECT
accDescr: Il client invia CONNECT al proxy, il proxy apre un tunnel TCP e restituisce 200, poi client e destinazione eseguono l'handshake TLS nel tunnel. Il log del proxy vede l'host, non il percorso URL
cli["Client"] -->|"CONNECT host:443"| px["Proxy"]
px -->|"200 e un tunnel TCP"| dest["Destinazione"]
dest -->|"TLS nel tunnel"| cli
px -.-> log["Log: solo host e successo"]
Figura 7: Un proxy pass-through vede l’host, non il percorso cifrato.
7.2. Proxy di ispezione TLS ed errori di certificato
I proxy dei prodotti di sicurezza, d’altra parte, includono un tipo di ispezione TLS (decifrazione SSL, break and inspect) che termina TLS, ispeziona i contenuti e ricifra prima di inoltrare. In questo schema il certificato server presentato al client non è quello vero; è sostituito da un certificato rifirmato dalla CA del proxy.13
La premessa che fa reggere questa configurazione è quindi «il certificato CA del proxy è stato distribuito alle radici attendibili di ogni client». Su una macchina che non l’ha ricevuto, o in un runtime che non guarda l’archivio certificati di Windows (strumenti con un proprio archivio di fiducia), avete un errore di convalida del certificato. In .NET emerge tipicamente come un HttpRequestException che avvolge un AuthenticationException (un messaggio del tipo «the remote certificate is invalid»).
I principi della correzione sono i seguenti.
- Distribuite il certificato CA interno all’archivio «Autorità di certificazione radice attendibili» del computer locale. La scissione tra archivio utente e archivio computer è trattata in «Guida pratica all’archivio certificati di Windows».
- Non disattivate la convalida dei certificati nel codice. Un workaround che restituisce sempre true da
ServerCertificateCustomValidationCallbackdiventa un’app vulnerabile che non può rilevare un man-in-the-middle nel momento in cui esce su una rete esterna. - Il traffico con pinning del certificato non può essere ispezionato in partenza. Le connessioni che verificano un certificato Microsoft specifico, come fanno alcuni componenti Windows, falliscono nel momento in cui il proxy scambia il certificato, e non c’è altro workaround se non un’esclusione.4 Per il traffico destinato a SaaS come Microsoft 365, Microsoft stessa raccomanda di escluderlo da decifrazione e ispezione a livello di rete.13
Un sintomo del tipo «ogni sito interno è visibile, ma solo un particolare servizio cloud produce un errore di certificato nell’app» dovrebbe farvi sospettare prima la combinazione dell’elenco di esclusione dell’ispezione TLS e del pinning.
flowchart TB
accTitle: Un proxy di ispezione TLS rifirma il certificato
accDescr: Il proxy termina TLS, ispeziona i contenuti e presenta un certificato rifirmato dalla propria CA. La convalida regge solo se quella CA è nelle radici attendibili. Non disattivate la convalida nel codice
real["Certificato server vero"] --> px["Proxy di ispezione TLS"]
px --> fake["Rifirmato dalla CA del proxy"]
fake --> client["Convalida del client"]
client -->|"CA nelle radici"| ok["Successo"]
client -->|"CA assente"| err["Errore di certificato"]
err -.-> fix["Distribuire la CA all'archivio"]
Figura 8: L’ispezione funziona solo come insieme con la distribuzione della CA interna.
8. La procedura di isolamento — cinque passi per identificare il colpevole
Indagate «non si connette» in modo meccanico in quest’ordine.
| Passo | Cosa fate | Cosa imparate |
|---|---|---|
| (1) Riprodurre | Accedere all’URL problematico con curl.exe -v o Invoke-WebRequest (meglio sulla stessa macchina, sotto lo stesso account) |
Se è un problema specifico dell’app o un problema di ambiente |
| (2) Raccogliere le impostazioni | Raccogliere le tre famiglie: netsh winhttp show proxy, le impostazioni per utente e le variabili d’ambiente |
Cosa c’è in quale famiglia |
| (3) Identificare l’account | Identificare l’account di esecuzione dell’app di destinazione (un servizio, Utilità di pianificazione, un altro utente) | Sotto quali impostazioni e quali credenziali sta girando |
| (4) Classificare l’errore | Distinguere 407 / 403 / fallimento di risoluzione del nome / timeout / errore di certificato | Isolare autenticazione proxy, rifiuto di criterio, percorso e ispezione TLS |
| (5) Log del proxy | Controllare l’ora corrispondente nel log di accesso del server proxy | Se ha raggiunto il proxy del tutto, e come chi ha autenticato |
Potete raccogliere (2) in un colpo solo con PowerShell.
# (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'
Alcuni consigli pratici.
- Nel test di riproduzione di (1), siate consapevoli di quale famiglia di impostazioni legge lo strumento. Il
curl.exeinbox di Windows può specificare un proxy in modo esplicito con-x http://proxy:8080, e per la convalida TLS usa di norma l’archivio certificati del sistema operativo (Schannel).Invoke-WebRequestdi Windows PowerShell 5.1 segue il lato .NET Framework (Opzioni Internet per default); PowerShell 7 segue il lato .NET (prima le variabili d’ambiente). «curl funziona ma l’app no» è di per sé un indizio di disallineamento tra famiglie di configurazione. - Se la destinazione in (3) è un servizio, ricontrollate (1) e (2) sotto lo stesso account del servizio. Un controllo nella sessione dell’amministratore non è prova di ciò che vede LocalSystem.
- Nella classificazione dell’errore di (4), prendete il capitolo 6 (autenticazione) come primo candidato per 407, il capitolo 7 (ispezione TLS) per un errore di certificato, e «non sta raggiungendo il proxy» (percorso, risoluzione del nome, firewall) per un timeout. Il pattern in cui la causa è una regola in ingresso del Firewall di Windows anziché il proxy è trattato in «Il firewall di Windows e le applicazioni aziendali».
- Se arrivate a (5) e non c’è ancora traccia nel log del proxy, il traffico non ha mai raggiunto il proxy. Sospettate la decisione DIRECT di PAC, un elenco di bypass o una variabile d’ambiente rimasta, e se serve confermate la destinazione reale con una cattura di pacchetti («Cattura di pacchetti su Windows in pratica — scegliere tra pktmon, netsh trace e Wireshark»).
flowchart TB
accTitle: Cinque passi per isolare un guasto del proxy
accDescr: Riprodurre sotto lo stesso account, raccogliere le tre famiglie di impostazioni, identificare l'account di esecuzione, classificare l'errore, poi controllare il log del proxy
s1["Riprodurre con curl"] --> s2["Raccogliere tre famiglie"]
s2 --> s3["Identificare l'account"]
s3 --> s4["Classificare l'errore"]
s4 --> s5["Controllare il log del proxy"]
s4 -.-> e407["407: autenticazione"]
s4 -.-> ecert["Errore di certificato: ispezione"]
s4 -.-> eto["Timeout: mai raggiunto"]
Figura 9: Percorrete i cinque passi in ordine. La classe di errore sceglie il capitolo successivo.
9. Una raccomandazione di progettazione — fate dell’app una su cui potete «configurare il proxy»
Capovolgete la procedura di indagine e diventa una linea guida di progettazione sul lato app. Per un’app Windows che consegnerete in un ambiente con proxy aziendale, si raccomanda quanto segue.
- Rendete il proxy configurabile dalle impostazioni dell’app. Il default è «seguire le impostazioni del sistema operativo». Nella maggior parte degli ambienti il default basta; solo negli ambienti eccezionali — PAC non può essere letto, gira come servizio, una configurazione proxy speciale — rendete possibile specificare un URL di proxy, un elenco di bypass e «non usare un proxy» da un file di impostazioni.
HttpClientHandler.Proxy/UseProxydella sezione 5.3 è il punto di implementazione.14 - Scrivete come le destinazioni interne (API, database, server di licenze e simili) sono trattate come eccezioni del proxy. Mettete in una forma che potete scrivere nella procedura di distribuzione se sono escluse da PAC DIRECT, un elenco di bypass o
NO_PROXY. Le regole di corrispondenza diNO_PROXY(niente caratteri jolly, che cosa significa un punto iniziale) sono ampiamente fraintese, quindi allegate esempi.7 - Progettate timeout e ritentativi presupponendo di passare da un proxy. Se il proxy è giù o bloccato sull’autenticazione, un’implementazione che aspetta un timeout predefinito lungo congela sia l’interfaccia sia le operazioni. Separate un timeout di connessione più breve e limitate i ritentativi alle richieste idempotenti (dettagli di progettazione in «Non racchiudere HttpClient in un using»).
- Registrate «quale proxy è stato usato». Fate in modo che l’app stessa possa rispondere alla prima domanda di un’indagine di guasto.
Un log come in (4) è già efficace se registra solo il risultato della risoluzione. Il punto è derivare il percorso dalle impostazioni (l’handler) che avete davvero usato per configurare il client. Se registrate HttpClient.DefaultProxy direttamente, registrerete un valore in disaccordo con il percorso reale quando l’handler specifica Proxy in modo esplicito o imposta UseProxy = false.
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);
Se all’avvio registrate una volta «percorso» e «account di esecuzione» per le destinazioni principali, i passi da (1) a (3) del capitolo 8 finiscono solo leggendo il log. Quando vi dicono «funziona nel browser, ma…», poter dire dal lato app «ho usato questa impostazione, e questo percorso» è la condizione di un’app forte contro i guai del proxy.
flowchart TB
accTitle: Rendere il proxy configurabile e registrare il percorso
accDescr: Per default seguire le impostazioni del sistema operativo, consentire un URL di proxy esplicito o un bypass o nessun proxy dalle impostazioni dell'app, e registrare la rotta usata davvero insieme all'account di esecuzione
def["Default: seguire le impostazioni del SO"] --> exc{"Ambiente eccezionale?"}
exc -->|"PAC illeggibile / servizio / speciale"| cfg["Impostare URL, bypass o nessun proxy"]
exc -->|"Caso usuale"| os["Usare il default del SO"]
cfg --> log["Registrare rotta e account"]
os --> log
Figura 10: Configurate quando dovete. Registrate sempre quale percorso è stato usato.
10. Sintesi
- Le impostazioni proxy di Windows si dividono in tre famiglie — impostazioni WinINET per utente, impostazioni macchina WinHTTP e variabili d’ambiente — e quale viene letta lo decidono l’app (il suo stack HTTP) e l’account di esecuzione.
- WinINET è per le app interattive e non è supportato per l’uso in un servizio; l’uso da servizio è il lavoro di WinHTTP (
netsh winhttp). Per «funziona a mano ma non come servizio», sospettate prima una differenza di account di esecuzione. netsh winhttp set proxyè un’impostazione statica e non gestisce PAC, rilevamento automatico né autenticazione. Su una rete operata in PAC dovete decidere come saranno trattati i client che non possono leggere PAC.FindProxyForURLdi PAC restituisce un proxy o DIRECT per URL. WPAD funziona solo su una rete che ha un dispositivo DHCP/DNS.- Il default di .NET Framework sono le Opzioni Internet dell’account di esecuzione (sovrascrivibile con
defaultProxy); .NET (Core e successivi) è variabili d’ambiente poi impostazioni proxy utente. Una specificazione esplicita (HttpClientHandler.Proxy) ha sempre la priorità più alta. - 407 è un errore di autenticazione del proxy; in un’app che gira sotto un account di servizio la causa tipica è che le «credenziali predefinite» diventano un’altra persona.
- Un proxy di ispezione TLS presuppone la distribuzione del certificato CA interno, e la risposta corretta a un errore di certificato è la distribuzione all’archivio certificati, non la disattivazione della convalida. Il traffico con pinning ha bisogno di un’esclusione.
- Isolate in modo meccanico nell’ordine «riprodurre → raccogliere le tre famiglie di impostazioni → identificare l’account di esecuzione → classificare l’errore → log del proxy». Sul lato app, una progettazione che «può configurare il proxy e registra il percorso che ha usato» è la migliore prevenzione.
La prossima volta che vi consultano con «solo l’app aziendale non si connette», chiedete prima questo.
Sotto l’account di chi sta girando quell’app, e quale delle tre famiglie di impostazioni proxy legge?
Quella sola domanda cambia molto l’ingresso dell’indagine.
Articoli correlati
- Non racchiudere HttpClient in un using ── guida pratica alla comunicazione HTTP nelle app aziendali C# (pattern di creazione, timeout, retry)
- Cattura di pacchetti su Windows in pratica — scegliere tra pktmon, netsh trace e Wireshark
- Il firewall di Windows e le applicazioni aziendali — registrate le regole in ingresso dall’installatore
- Come creare e gestire un servizio Windows — dalla scelta tra Utilità di pianificazione e servizi al trasformare un BackgroundService in un servizio Windows
- NTLM e Kerberos spiegati con i diagrammi — perché l’autenticazione ricade su NTLM
- Guida pratica all’archivio certificati di Windows — utente o computer, quale dovreste usare?
Aree di consulenza correlate
KomuraSoft LLC gestisce l’indagine dei problemi di comunicazione delle app Windows in ambienti di proxy aziendale, proxy con autenticazione e ispezione TLS — «funziona sulla macchina di sviluppo ma non comunica sulla rete del cliente», «dopo averla trasformata in servizio non raggiungeva più l’API esterna» — e la consulenza sulla progettazione della comunicazione di app aziendali che presuppone un ambiente proxy (voci di impostazione, timeout, progettazione dei log). Va bene partire dall’ordinare i passi di riproduzione e come raccogliere i log.
- Sviluppo di applicazioni Windows
- Analisi dei bug e delle cause
- Consulenza tecnica e revisione del progetto
- Contattaci
Riferimenti
-
Microsoft Learn, WinINet vs. WinHTTP. Sulla guida a usare WinINET a meno che non siate in un servizio o in un processo che ha bisogno di impersonation e isolamento di sessione, e sulla tabella di confronto delle funzionalità che copre cache delle credenziali, prompt delle credenziali, supporto dei servizi, impersonation, isolamento di sessione e simili. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, netsh winhttp. Sulla sintassi di netsh winhttp show/set/import/reset; proxy-server e bypass-list di set proxy; import proxy source=ie; e le impostazioni proxy dettagliate in forma JSON (Proxy, ProxyBypass, AutoconfigUrl, AutoDetect) via set advproxy. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, About WinHTTP. Su WinHTTP come stack HTTP progettato per uso da servizio e lato server, che supporta l’esecuzione sotto un account di servizio e l’impersonation, e non condivide cookie, cache, credenziali del browser né le Opzioni Internet dell’utente. ↩ ↩2 ↩3
-
Microsoft Learn, Using a proxy with Delivery Optimization. Sul fatto che netsh winhttp set proxy è un’impostazione statica che non supporta rilevamento automatico, un URL PAC né autenticazione proxy; sulla configurazione proxy per dispositivo per contesti senza utente connesso (CSP NetworkProxy, il criterio «Rendi le impostazioni proxy per macchina»); e sul traffico con pinning del certificato che fallisce sotto ispezione TLS e ha bisogno di un’esclusione. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, WinHTTP AutoProxy Support. Sul fatto che uno script PAC contiene una funzione FindProxyForURL(url, host) che calcola un elenco di proxy per richiesta e indica una connessione diretta con un valore di ritorno speciale, e sul fatto che la più vecchia API AutoProxy non integra automaticamente il proxy automatico nello stack HTTP, quindi l’app deve chiamare WinHttpGetProxyForUrl. ↩ ↩2 ↩3
-
Microsoft Learn, WinHttpGetProxyForUrl function. Sul fatto che è un’implementazione del protocollo WPAD, che va chiamata per URL perché un file PAC può restituire un proxy diverso per URL, e che supporta sia un URL PAC esplicito sia il rilevamento automatico dalla rete. ↩ ↩2
-
Microsoft Learn, HttpClient.DefaultProxy Property. Sul fatto che Windows legge prima le variabili d’ambiente HTTP_PROXY, HTTPS_PROXY, ALL_PROXY e NO_PROXY e, se sono indefinite, le impostazioni proxy utente; che Linux si inizializza senza proxy se le variabili d’ambiente sono assenti; che NO_PROXY non supporta i caratteri jolly e usa una corrispondenza di sottodominio con punto iniziale; e che un URL di proxy può includere nome utente e password. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, Configuring Internet Applications. Sul fatto che l’elemento defaultProxy definisce il proxy predefinito su .NET Framework; che un HttpWebRequest senza proprietà Proxy usa il proxy predefinito; e che le impostazioni Internet di sistema e quelle del file di configurazione sono combinate con priorità al lato file di configurazione. ↩ ↩2 ↩3
-
Microsoft Learn, defaultProxy element (network settings). Sugli attributi enabled e useDefaultCredentials dell’elemento system.net/defaultProxy, gli elementi figlio proxy, bypasslist e module, sul fatto che si usano le impostazioni proxy del sistema se l’elemento è vuoto, e sulla configurazione con HttpClient.DefaultProxy in migrazione a .NET 6 e successivi. ↩ ↩2 ↩3
-
Microsoft Learn, Authentication in WinHTTP. Sul fatto che il codice di stato 407 e un’intestazione Proxy-Authenticate vengono restituiti quando è richiesta l’autenticazione del proxy (l’autenticazione del server è 401 e WWW-Authenticate); sulla differenza tra autenticazione Basic e schemi challenge/response come Kerberos; e sul fatto che uno schema challenge/response significa che nome utente e password non viaggiano in rete. ↩ ↩2 ↩3
-
Microsoft Learn, HttpClientHandler.DefaultProxyCredentials Property. Sulla proprietà che imposta le credenziali usate per autenticarsi al proxy predefinito quando UseProxy è true e Proxy è null, in modo da usare il proxy predefinito di sistema. ↩ ↩2
-
Microsoft Learn, WebProxy.Credentials Property. Sul fatto che la proprietà Credentials sono le credenziali inviate al proxy in risposta a HTTP 407, e sulla raccomandazione in molti scenari client di impostare UseDefaultCredentials a true in modo da usare le credenziali predefinite dell’utente connesso. ↩ ↩2
-
Microsoft Learn, Understanding implications when using network intermediation to decrypt or manipulate Microsoft 365 traffic at the network layer. Sul fatto che l’ispezione TLS (decifrazione SSL) è una configurazione in cui un proxy o un firewall decifra, ispeziona e ricifra TLS; che può causare malfunzionamento e degrado delle prestazioni in servizi che presuppongono TLS end-to-end; e sulla raccomandazione di escludere il traffico destinato a Microsoft 365 da decifrazione e ispezione a livello di rete. ↩ ↩2 ↩3
-
Microsoft Learn, Make HTTP requests with the HttpClient class. Sui due metodi di configurazione HttpClient.DefaultProxy e HttpClientHandler.Proxy; sul fatto che una specificazione Proxy ha priorità sul file di configurazione e sulle impostazioni del computer locale; sulla configurazione WPAD tipica di ottenere un file PAC (wpad.dat e simili) tramite il nome DNS wpad o DHCP; e sul giudizio di bypass delle destinazioni locali per nome piatto, loopback e corrispondenza del suffisso di dominio. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, WinHttpOpen function. Sul significato di ciascun valore dwAccessType. WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY (Windows 8.1 e successivi) decide automaticamente il proxy dalle impostazioni proxy di sistema/utente e gestisce anche failover e autenticazione in automatico, e WINHTTP_ACCESS_TYPE_DEFAULT_PROXY è deprecato da 8.1 in poi. ↩
-
Microsoft Learn, Work with existing on-premises proxy servers. Sul fatto che l’HTTPS in uscita si stabilisce con una richiesta CONNECT al proxy; che il successo restituisce HTTP 200; e che risposte come 407 (autenticazione richiesta) o 502 indicano che il proxy non sta permettendo la comunicazione, quindi dovreste procedere all’isolamento con il team lato proxy. ↩
Articoli correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Non racchiudere HttpClient in un using ── guida pratica alla comunicazione HTTP nelle app aziendali C# (pattern di creazione, timeout, retry)
Creare un nuovo HttpClient con using a ogni richiesta esaurisce i socket, mentre renderlo static non segue i cambi di DNS: analizziamo il...
Cattura dei pacchetti su Windows in pratica — scegliere tra pktmon, netsh trace e Wireshark
Un guasto che nel log dell'app lascia solo «timeout» si indaga uno strato più in basso, guardando i pacchetti realmente passati sul filo....
Come comprendere l'isolamento delle sessioni di Windows — Session 0, RDP ed esecuzione simultanea di più utenti
Questo articolo chiarisce il concetto di «sessione» di Windows, un argomento che genera costante confusione tra gli sviluppatori di appli...
Outsourcing e sviluppo su commissione di app Windows: cosa chiarire prima di affidare l'incarico
Prima di affidare in outsourcing o su commissione lo sviluppo di un'app Windows, ecco i punti da chiarire: revisione del software esisten...
Checklist per gestire in sicurezza processi figli nelle app Windows - Job Object, propagazione exit, stdio e watchdog
Come far morire i processi figli con il padre su Windows: Job Object, propagazione exit, drenaggio stdout/stderr e posizionamento del wat...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Sviluppo di applicazioni Windows
Applicazioni aziendali, integrazione di dispositivi e strumenti di comunicazione, dai requisiti allo sviluppo.
Domande frequenti
Domande che ricorrono nelle consulenze sull’argomento dell’articolo.
- Il browser si connette, ma solo l'app aziendale non passa il proxy aziendale. Perché?
- Il browser legge le impostazioni proxy per utente di WinINET, ma un'app aziendale non legge necessariamente le stesse. Un'app che gira come servizio Windows, o sotto un altro account, consulta le impostazioni visibili da quell'account, le impostazioni macchina di WinHTTP o le variabili d'ambiente. Prima identificate l'account di esecuzione e controllate le impostazioni proxy visibili da quell'account sia con netsh winhttp show proxy sia nelle impostazioni utente. Se potete riprodurre con curl.exe o simile sotto lo stesso account sulla stessa macchina, potete trattarlo come un disallineamento tra famiglie di configurazione, non come un problema specifico dell'app.
- Ho impostato netsh winhttp set proxy, ma il traffico dell'app non è cambiato. Perché?
- Ciò che netsh winhttp imposta è il default macchina di WinHTTP. Non influisce su browser o app interattive che leggono WinINET, né su HttpClient di .NET (Core e successivi), che preferisce le variabili d'ambiente. netsh winhttp set proxy è anche un'impostazione statica; non gestisce autoconfigurazione PAC, rilevamento automatico né autenticazione proxy. Dovete prima confermare quale stack HTTP usa l'app di destinazione e da quale famiglia di configurazione risolve il proxy.
- Quali impostazioni proxy legge un'app .NET?
- .NET Framework usa per default le Opzioni Internet (equivalente WinINET) dell'account di esecuzione, e potete sovrascriverle con l'elemento system.net/defaultProxy in app.config. HttpClient su .NET (Core e successivi) legge prima le variabili d'ambiente HTTP_PROXY, HTTPS_PROXY e NO_PROXY e, se non sono definite, ricade sulle impostazioni proxy utente di Windows. In entrambi i casi un HttpClientHandler.Proxy esplicito ha priorità. L'ordine di risoluzione predefinito differisce quindi tra Framework e Core e successivi, quindi dovete ricontrollare il comportamento del proxy in migrazione.
- Cosa dovrei controllare quando viene restituito 407 Proxy Authentication Required?
- 407 è un segnale che il proxy stesso sta chiedendo autenticazione; è una cosa diversa da un errore di autenticazione del server di destinazione (401). Prima confermate lo schema di autenticazione che il proxy chiede (Negotiate, NTLM, Basic) dall'intestazione Proxy-Authenticate, e in .NET passate le credenziali con HttpClientHandler.DefaultProxyCredentials o WebProxy.UseDefaultCredentials. In un'app che gira sotto un account di servizio, le «credenziali predefinite» diventano quelle di quell'account di servizio, quindi l'incidente tipico è che funziona per un utente interattivo e poi dà 407 appena la trasformate in servizio. Controllate anche nel log lato proxy come chi ha autenticato.
- Un proxy di ispezione TLS produce errori di certificato. Posso disattivare la convalida dei certificati?
- Disattivarla non è raccomandato. Un proxy di ispezione TLS decifra il traffico e poi presenta al client un certificato rifirmato dalla propria CA, quindi la convalida fallisce se quel certificato CA non è nelle radici attendibili. La correzione corretta è distribuire il certificato CA interno all'archivio certificati di Windows (di solito Autorità di certificazione radice attendibili del computer locale). Disattivare la convalida nel codice significa che un attacco man-in-the-middle non può essere rilevato quando l'app è usata su una rete esterna, e la vulnerabilità rimane.
Profilo dell’autore
Pagina di presentazione dell’autore dell’articolo.
Go Komura
Rappresentante di KomuraSoft LLC
Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.