История изменений (1 обновлений, последнее 31 Aug 2026)
Журнал изменений этой статьи. Там, где версия до правки была заархивирована, она остаётся доступной для чтения по постоянной ссылке с DOI.
- Русский текст переписан по текущему навыку технического перевода как полный перевод японского оригинала.
- Первая публикация
Цитирование статьи(DOI (зарегистрированный архив): 10.5281/zenodo.22176230)
Приведённые ниже DOI относятся к ранее зарегистрированным архивным версиям, которые могут отличаться от текущего текста. Для ссылки на текущий текст используйте URL этой страницы.
Го Комура (2026). Корпоративный прокси и приложения Windows — как WinINET, WinHTTP и .NET выбирают прокси. KomuraSoft LLC. https://comcomponent.com/ru/blog/windows-proxy-wininet-winhttp-dotnet/
- DOI (зарегистрированный архив)
- 10.5281/zenodo.22176230
- DOI (последняя зарегистрированная версия)
- 10.5281/zenodo.22176231
«Браузер открывает внешние сайты, а бизнес-приложение не достучится до внешнего API». «На машине разработчика всё работает, а в сети заказчика — таймаут». «Если запустить вручную, связь есть; как только ставишь службу Windows — падает». Когда бизнес-приложение крутится в среде с корпоративным прокси, такие обращения — почти классика.
В большинстве случаев дело не в поломке прокси-сервера и не в баге приложения. В Windows то, что называют «параметрами прокси», живёт в нескольких независимых источниках, и какой из них читает процесс, зависит от HTTP-стека приложения и от учётной записи, от которой оно запущено. Параметры, которые читает браузер, которые читает служба и которые читает HttpClient в .NET, могут не совпадать. Как только эта схема ясна, разбор «в браузере работает, а в приложении нет» идёт заметно быстрее.
Статья для ИТ-специалистов малых и средних компаний и разработчиков Windows-приложений. Здесь в одной картине: три источника параметров прокси — WinINET, WinHTTP и переменные окружения; автоконфигурация PAC и WPAD; разница выбора прокси в .NET Framework и в .NET (Core и новее); прокси с аутентификацией (407); инспекция TLS; практическая диагностика. Как создавать HttpClient и как проектировать таймауты разобрано в «Не оборачивайте HttpClient в using», поэтому здесь речь только о том, как выбирается прокси.
1. Сначала выводы
- Параметры прокси Windows — не одна вещь; есть как минимум три источника. (1) Пользовательские параметры WinINET (страница «Прокси» в «Параметрах» = прежние параметры интернета), (2) машинные параметры WinHTTP (
netsh winhttp) и (3) переменные окруженияHTTP_PROXY/HTTPS_PROXY. Какой из них читается, решает само приложение.12 - «Прокси», который вы видите в «Параметрах», — это пользовательские параметры WinINET. Браузеры и интерактивные приложения их читают; службы Windows — нет. WinINET в службе не поддерживается; для служб предназначен WinHTTP.13
- Самая частая причина «вручную работает, как служба — нет» — другая учётная запись процесса. LocalSystem и учётная запись службы не видят пользовательский прокси, который администратор настроил на своём экране.34
netsh winhttp set proxy— статическая настройка: PAC, автоопределение и аутентификация прокси в неё не входят. Если PAC или WPAD нужно задать на уровне компьютера, это ужеnetsh winhttp set advproxy.42- Результат PAC зависит от URL. Функция
FindProxyForURLв файле PAC принимает URL и имя узла и возвращает список прокси или прямое подключение (DIRECT). «Тот сайт открывается, а этот API — нет» нередко оказывается веткой PAC.56 - HttpClient в .NET (Core и новее) инициализирует прокси по умолчанию в порядке: переменные окружения → пользовательские параметры прокси Windows. Если задана любая из
HTTP_PROXY,HTTPS_PROXYилиALL_PROXY, она важнее параметров ОС. Отсюда типичный сбой: «кто-то забыл переменную окружения».7 - В .NET Framework по умолчанию берутся параметры интернета учётной записи процесса; их можно переопределить через
defaultProxyв app.config. Настройки файла конфигурации важнее системных.89 - 407 — ошибка аутентификации прокси, это не 401 (аутентификация сервера). Схемы — Negotiate, NTLM, Basic и другие; в .NET учётные данные передают через
DefaultProxyCredentialsилиWebProxy.UseDefaultCredentials. Под учётной записью службы содержимое «учётных данных по умолчанию» уже другое.101112 - Прокси с инспекцией TLS работает только вместе с распространением внутреннего сертификата CA. На машинах и в средах выполнения, куда сертификат не доехал, проверка сертификата падает. Это лечат распространением в хранилище сертификатов, а не отключением проверки в приложении.134
Одной фразой: когда вы говорите «я проверил параметры прокси», всегда умейте назвать, какой из трёх источников вы смотрели и от какой учётной записи — в этом и есть тема статьи.
На схеме сплошная линия обозначает отношение, которое выполняется всегда, а пунктирная — условное отношение (условия указаны в пояснении к каждому отношению на странице сведений). Полный список отношений (всего 19, с доказательствами и степенью уверенности) и определения основных понятий собраны на странице сведений карты знаний (на японском). Данные: JSON-LD / Turtle
2. В Windows «параметры прокси» живут в трёх источниках
Сначала карта целиком. Пути, по которым приложение Windows находит корпоративный прокси, распадаются на три источника.
| Источник настроек | Где задаёте / команда | Область | Кто в основном читает |
|---|---|---|---|
| (1) WinINET (параметры интернета) | Параметры → Сеть и Интернет → Прокси, inetcpl.cpl |
На пользователя (по умолчанию) | Браузеры, интерактивные настольные приложения, умолчание .NET Framework |
| (2) WinHTTP (машинные параметры) | netsh winhttp set proxy / set advproxy |
Компьютер | Службы Windows, часть компонентов ОС |
| (3) Переменные окружения | HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY |
Процесс (наследуются в зависимости от того, где заданы) | HttpClient в .NET (Core и новее), curl, кроссплатформенные инструменты вроде Node.js и Python |
(1) — то, что обычно имеют в виду под «параметрами прокси Windows»; по сути это конфигурация WinINET. Исторически это параметры интернета Internet Explorer, и по умолчанию они хранятся на каждого пользователя.4
(2) — параметры по умолчанию на уровне компьютера для контекстов вроде службы, где «вошедшего пользователя нет». (3) — в основном соглашение кроссплатформенных инструментов; в Windows их тоже читают .NET (Core и новее), curl и подобные.7
Важный момент: какой источник читается, решает само приложение, а не «настройки Windows». Если внутри приложения WinINET, оно читает (1); если WinHTTP — (2) (или своё явное указание); если .NET (Core и новее) — сначала (3), затем (1). Обычно это не «параметры прокси верные, а подключиться всё равно нельзя». На деле «приложение читало другой источник, чем тот, который вы проверяли».
flowchart TB
accTitle: Три источника параметров прокси Windows
accDescr: WinINET — пользовательские Параметры и параметры интернета, WinHTTP — машинные параметры через netsh, переменные окружения — область процесса. Какой источник читается, решает приложение, а не сторона настроек
fam{"Какой источник?"}
fam --> wininet["Пользовательские параметры WinINET"]
fam --> winhttp["Машинные параметры WinHTTP"]
fam --> env["HTTP_PROXY и родственные"]
wininet -.-> r1["Браузеры и настольные приложения"]
winhttp -.-> r2["Службы и часть компонентов ОС"]
env -.-> r3[".NET Core+ и curl"]
Рис. 1: Три источника стоят рядом. Какой из них читать, выбирает приложение.
Если включить групповую политику «Make proxy settings per-machine (rather than per-user)» (задавать параметры прокси на уровне компьютера, а не пользователя), (1) можно переключить на машинные и раздать одни и те же параметры всем пользователям. Через MDM (Intune и аналоги) то же самое задают на устройство CSP NetworkProxy.4
3. WinINET и WinHTTP — для интерактивных приложений и для служб
3.1. Чем они отличаются
WinINET и WinHTTP — оба штатные HTTP-клиентские стеки Windows, но рассчитаны на разное использование.
- WinINET: для интерактивных настольных приложений. Сам подхватывает параметры интернета пользователя (прокси, cookie, кэш учётных данных) и при необходимости может показать окно ввода учётных данных. В службе и в процессе, похожем на службу, не поддерживается.1
- WinHTTP: для служб и серверной стороны. Умеет работать под учётной записью службы, олицетворять поток (impersonation) и изолировать сеансы; взамен не разделяет настройки браузера пользователя, cookie и учётные данные. Окна тоже не показывает.3
У самой Microsoft формулировка прямая: «используйте WinINET, если только вы не работаете внутри службы или в служебном процессе, которому нужны изоляция сеансов и олицетворение» — иначе говоря, если это служба, берите WinHTTP.1
flowchart TB
accTitle: WinINET для интерактивных приложений, WinHTTP для служб
accDescr: WinINET наследует параметры интернета вошедшего пользователя и в службе не поддерживается. WinHTTP работает под учётной записью службы без интерфейса и не разделяет настройки браузера пользователя
q{"Интерактивное настольное приложение?"}
q -->|"Да"| ie["WinINET"]
q -->|"Служба или подобное"| wh["WinHTTP"]
ie -.-> ieNote["Читает параметры интернета пользователя"]
wh -.-> whNote["Машинные параметры, без UI"]
Рис. 2: Интерактивные приложения используют WinINET. Служба использует WinHTTP.
3.2. Базовые операции netsh winhttp
Машинный прокси по умолчанию WinHTTP задают через netsh.2
:: Показать текущие параметры прокси WinHTTP
netsh winhttp show proxy
:: Задать статический прокси (со списком исключений)
netsh winhttp set proxy proxy-server="proxy.example.co.jp:8080" bypass-list="*.example.co.jp;<local>"
:: Подтянуть параметры интернета (WinINET)
netsh winhttp import proxy source=ie
:: Вернуть умолчание (DIRECT)
netsh winhttp reset proxy
Два ограничения, которые стоит держать в голове.
netsh winhttp set proxy— статическая настройка. Ни автоопределение прокси, ни URL PAC, ни аутентификация прокси сюда не входят.4import proxy source=ieкопирует только статику на момент выполнения; дальше за изменениями параметров интернета он не следит. Если на уровне компьютера нужны PAC или автоопределение, подробные параметры в JSON (Proxy,ProxyBypass,AutoconfigUrl,AutoDetect) задают черезnetsh winhttp set advproxy.2
3.3. Самая частая ловушка: служба не читает настройки IE пользователя
Самый частый полевой сценарий по шагам выглядит так.
- Разработчик запускает инструмент на своём ПК → срабатывают его пользовательские параметры прокси (1), всё работает
- В продуктиве оставляют крутиться как службу Windows (Как создавать и эксплуатировать службы Windows) под LocalSystem
- Из LocalSystem виден другой набор (пользовательские параметры невидимы, машинные параметры WinHTTP не заданы = DIRECT) → процесс пытается идти к внешнему API напрямую и уходит в таймаут
Это не «на той же машине не работает». Даже на той же машине другая учётная запись процесса означает другой видимый набор параметров прокси. Для процесса, которому нужно ходить в сеть без вошедшего пользователя, правильный ход — задать параметры на уровне компьютера в том виде, который HTTP-стек этого процесса реально читает. У собственного приложения или компонента Windows на WinHTTP сработают параметры WinHTTP из netsh.4 HttpClient в .NET (Core и новее), напротив, машинные параметры WinHTTP не читает (см. главу 5), поэтому для службы на .NET задайте системную переменную окружения (HTTPS_PROXY и аналоги) или явно укажите HttpClientHandler.Proxy из настроек приложения.
Сбой бывает и в другую сторону. Если на ноутбуке, который бывает и в офисе, и вне корпоративной сети, жёстко прописать статический прокси через netsh winhttp set proxy, вне офиса этот прокси недоступен и связь пропадает целиком. Машинную статику считайте средством для серверов, у которых сеть не меняется.4
flowchart TB
accTitle: Почему служба не видит настройки IE пользователя
accDescr: Запуск разработчиком читает пользовательские параметры WinINET и работает. Как LocalSystem эти параметры невидимы. Собственное приложение WinHTTP тогда следует незаданным машинным параметрам (DIRECT). Служба .NET Core+ по-прежнему использует переменные окружения или явный handler.Proxy и не переключается на netsh winhttp
dev["Запуск вручную от пользователя"] --> ok["Применяются пользовательские параметры WinINET"]
svc["Служба Windows как LocalSystem"] --> miss["Пользовательские параметры невидимы"]
miss --> stack{"Какой HTTP-стек?"}
stack -->|"WinHTTP"| direct["WinHTTP не задан = DIRECT"]
stack -->|".NET Core+"| env["Переменные окружения или handler.Proxy"]
direct --> fail["Внешний API уходит в таймаут"]
Рис. 3: Та же машина, другая учётная запись — другой видимый набор параметров прокси.
4. PAC и WPAD — что на самом деле стоит за «автоконфигурацией»
4.1. Файлы PAC и FindProxyForURL
Файл PAC (Proxy Auto-Configuration) — это JavaScript (ECMAScript), который вычисляет, какой прокси взять для данного URL, и всегда содержит функцию FindProxyForURL(url, host). Функция возвращает список прокси либо особое значение DIRECT — «можно идти напрямую, без прокси».5
function FindProxyForURL(url, host) {
// Внутренние домены и частные адреса — напрямую
if (dnsDomainIs(host, ".example.co.jp") ||
isInNet(host, "10.0.0.0", "255.0.0.0")) {
return "DIRECT";
}
// Остальное — через прокси. Если первый недоступен, берём следующий
return "PROXY proxy1.example.co.jp:8080; PROXY proxy2.example.co.jp:8080; DIRECT";
}
Отсюда два практических следствия.
- Прокси нужно выбирать для каждого URL. PAC может вернуть другой прокси или прямое подключение в зависимости от URL (узла), поэтому автопрокси WinHTTP тоже устроен так, чтобы каждый раз передавать URL запроса и спрашивать заново.6 «Браузер открывает другой сайт» не доказывает, что проблемный API идёт тем же путём.
- DIRECT — указание «идти без прокси». Если трафик, который должен быть внутренним, так и не появляется в журнале прокси, сначала проверьте, не вернул ли PAC DIRECT (или не попал ли узел в список исключений).
4.2. Автоопределение через WPAD
Включите «Определять параметры автоматически» — и машина ищет расположение файла PAC по протоколу WPAD (Web Proxy Auto-Discovery). В типичной схеме DHCP раздаёт URL PAC либо через DNS ищут узел с именем wpad и скачивают PAC с URL вроде http://wpad/wpad.dat.14
Иными словами, «автоопределение» — не магия. Это механизм, который работает только в сети, где в DHCP/DNS уже заложена инфраструктура WPAD. Включить одно автоопределение в сети без этой инфраструктуры — лишь добавить ожидание неудачного поиска.
flowchart TB
accTitle: PAC выбирает прокси по URL, WPAD только находит PAC
accDescr: FindProxyForURL принимает URL и узел и возвращает список прокси или DIRECT. WPAD находит PAC только через DHCP или DNS. Клиент, который не может вычислить PAC, переключается на статический прокси или переменные окружения
url["URL запроса"] --> pac["FindProxyForURL"]
pac -->|"список прокси"| via["Идти через прокси"]
pac -->|"DIRECT"| dir["Подключаться без прокси"]
wpad["WPAD через DHCP или DNS"] -.-> pac
nopac["Клиент не вычисляет PAC"] -.-> fb["Статические параметры или переменные окружения"]
Рис. 4: PAC решает по URL. WPAD только находит файл PAC.
4.3. Как ведут себя клиенты, которые не могут вычислить PAC
Не каждый клиент умеет вычислить PAC.
- Статические параметры
netsh winhttp set proxyPAC не вычисляют.4 - Инструменты в стиле переменной
HTTP_PROXYкак правило принимают только фиксированный URL прокси (поля для URL PAC нет).7 - У собственного приложения, которое вызывает WinHTTP напрямую, всё зависит от того, как открыта сессия. Приложение, открытое через
WinHttpOpenв Windows 8.1 и новее сWINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, получает от WinHTTP автоматический выбор системных/пользовательских параметров прокси (включая WPAD/PAC) на каждый запрос.15 Если открыто более старымWINHTTP_ACCESS_TYPE_DEFAULT_PROXY(с 8.1 не рекомендуется) или аналогом, автопрокси в HTTP-стек не встроен, и приложение само должно вызватьWinHttpGetProxyForUrlи применить результат к запросу. Иначе говоря, в старой реализации PAC может быть, но не использоваться.5
«Браузер по PAC попадает на правильный прокси, а бизнес-приложение PAC не читает, пытается идти напрямую и падает» — ещё одно классическое расхождение. В сети на PAC для клиентов, которые PAC не читают, заранее решите запасной путь: статику или переменные окружения.
5. Выбор прокси в .NET — у Framework и у Core это разные вещи
Какие параметры прокси читает приложение .NET, по умолчанию различается между .NET Framework и .NET (Core и новее). Если перепутать, начнёте смотреть приложение на .NET 8 глазами эпохи Framework и промахнётесь.
5.1. .NET Framework — по умолчанию параметры интернета, переопределяется defaultProxy
В .NET Framework HttpWebRequest и сидящий на нём HttpClient используют прокси по умолчанию, если Proxy не задан явно. Этот прокси складывается из интернет-параметров системы (параметры WinINET учётной записи процесса) и файла конфигурации, и настройки файла конфигурации важнее.8
Этим умолчанием управляет элемент system.net/defaultProxy в app.config (или machine.config).9
<configuration>
<system.net>
<!-- useDefaultCredentials: отправлять ли прокси с аутентификацией учётные данные по умолчанию -->
<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>
Оставьте элемент defaultProxy пустым — используются системные параметры (параметры интернета); пропишите proxyaddress и аналоги — они важнее. Из программы то же умолчание можно заменить через WebRequest.DefaultWebProxy.98
Ловушка раздела 3.3 действует и здесь. Поскольку умолчание — «параметры интернета учётной записи процесса», приложение .NET Framework под учётной записью службы читает другой (обычно пустой) набор, чем тот, что виден на рабочем столе администратора.
5.2. .NET (Core и новее) — сначала переменные окружения, затем пользовательские параметры ОС
У HttpClient в .NET (Core и новее) есть статическое свойство HttpClient.DefaultProxy. Если обработчик не указывает прокси явно, каждый экземпляр HttpClient его использует. Правило инициализации в Windows: «читать переменные окружения; если они не заданы — читать пользовательские параметры прокси».7
Используются такие переменные окружения.7
| Переменная окружения | Смысл |
|---|---|
HTTP_PROXY |
Прокси для HTTP-запросов |
HTTPS_PROXY |
Прокси для HTTPS-запросов |
ALL_PROXY |
Запасной вариант, если две предыдущие не заданы |
NO_PROXY |
Список узлов через запятую, для которых прокси не использовать |
Три вещи, за которыми следить.
- Если задана любая из
HTTP_PROXY,HTTPS_PROXYилиALL_PROXY, она важнее параметров прокси ОС. Задать толькоNO_PROXYпрокси из переменных окружения не включает: в Windows по-прежнему берутся пользовательские параметры прокси ОС. «Невидимые настройки» вроде системнойHTTPS_PROXY, забытой после старого эксперимента, или шаблона CI/CD, который её подставляет, — типичный источник сбоев. NO_PROXYне поддерживает подстановочные знаки (*). Чтобы захватить поддомен, поставьте точку в начале (.example.comсовпадает сwww.example.com, но не с самимexample.com).7- Вне Windows (контейнеры Linux и аналоги), если переменные окружения не заданы, инициализация идёт без прокси. Что одно и то же приложение по умолчанию ведёт себя по-разному на Windows и на Linux, стоит проверить при переносе в контейнер.7
5.3. Явное указание — HttpClientHandler.Proxy и UseProxy
На любой среде выполнения наивысший приоритет — явное указание на обработчике. HttpClientHandler.Proxy важнее параметров ОС и файла конфигурации, а UseProxy = false не использует прокси вовсе.14
using System.Net;
// Явно использовать прокси из настроек приложения
var handler = new HttpClientHandler
{
Proxy = new WebProxy("http://proxy.example.co.jp:8080")
{
BypassProxyOnLocal = true,
BypassList = new[] { @"^intra\.example\.co\.jp$" },
UseDefaultCredentials = true // Прокси с аутентификацией: отвечать учётными данными процесса
},
UseProxy = true
};
var client = new HttpClient(handler);
// Клиент без прокси (для прямого доступа к внутренним API)
var directHandler = new HttpClientHandler { UseProxy = false };
var directClient = new HttpClient(directHandler);
Если явного указания нет и берутся параметры ОС, у автоматического обхода локальных назначений есть правила. Короткое имя без точки, loopback-адрес, назначение, совпадающее с DNS-суффиксом самой машины, и подобное могут считаться «локальными».14 Явления вроде «по IP поведение другое» или «поставил FQDN — и вдруг пошло через прокси» нередко вызваны именно этой проверкой.
Порядок приоритета такой.
| Приоритет (высокий → низкий) | .NET Framework | .NET (Core и новее) |
|---|---|---|
| 1 | Явное указание вроде HttpClientHandler.Proxy |
То же |
| 2 | defaultProxy в app.config |
Присваивание HttpClient.DefaultProxy |
| 3 | Параметры интернета учётной записи процесса | Переменные окружения (HTTP_PROXY и другие) |
| 4 | — | Пользовательские параметры прокси Windows |
flowchart TB
accTitle: Выбор прокси по умолчанию в Framework против Core и новее
accDescr: Явный HttpClientHandler.Proxy всегда побеждает. Framework затем использует app.config defaultProxy и параметры интернета учётной записи процесса. Core и новее использует присваивание HttpClient.DefaultProxy, затем переменные окружения, затем пользовательские параметры прокси Windows
expl["Явный handler.Proxy"] --> done["Используется этот прокси"]
noexpl["Нет явного Proxy"] --> fw{"Какая среда выполнения?"}
fw -->|"Framework"| cfg["app.config defaultProxy"]
cfg --> ie["Параметры интернета учётной записи"]
fw -->|"Core и новее"| dp["HttpClient.DefaultProxy"]
dp --> ev["HTTP_PROXY и родственные"]
ev --> user["Пользовательские параметры прокси Windows"]
Рис. 5: Явное указание всегда побеждает. Путь по умолчанию зависит от среды выполнения.
6. Прокси с аутентификацией — 407 это ошибка аутентификации прокси
6.1. Не путайте 407 с 401
Когда вы пытаетесь пройти через прокси, который требует аутентификации, прокси возвращает код состояния 407 (Proxy Authentication Required) и заголовок Proxy-Authenticate со списком доступных схем. Это не требование аутентификации сервера назначения (401 и WWW-Authenticate): и сторона, которой передают учётные данные, и место, где их задают, другие.10
flowchart TB
accTitle: 407 это прокси, 401 это сервер назначения
accDescr: 407 и Proxy-Authenticate приходят от прокси. 401 и WWW-Authenticate приходят от сервера назначения. Учётные данные и место настройки различаются
req["Исходящий запрос"] --> who{"Кто требует аутентификацию?"}
who -->|"Прокси"| e407["407 + Proxy-Authenticate"]
who -->|"Назначение"| e401["401 + WWW-Authenticate"]
e407 -.-> cred["DefaultProxyCredentials"]
Рис. 6: 407 — аутентификация прокси. 401 — аутентификация сервера.
Схемы включают Basic, который отправляет имя пользователя и пароль как есть, и схемы «вызов — ответ» вроде Negotiate (Kerberos/NTLM). В схеме «вызов — ответ» сам пароль по сети не идёт, и аутентификация завершается за несколько обменов.10 Механизм, на какую схему проверка «скатывается», подробнее разобран в «NTLM и Kerberos на схемах».
6.2. Как передать учётные данные в .NET
Если хотите использовать прокси по умолчанию из параметров ОС и только провести аутентификацию, используйте HttpClientHandler.DefaultProxyCredentials. Это учётные данные, которые отправляются тому прокси по умолчанию, когда UseProxy = true и Proxy = null (= системный прокси по умолчанию).11
using System.Net;
var handler = new HttpClientHandler
{
UseProxy = true, // Значение по умолчанию. Вместе с Proxy = null берётся системный прокси
Proxy = null,
// Ответить на 407 учётными данными процесса (вошедший пользователь или учётная запись службы)
DefaultProxyCredentials = CredentialCache.DefaultCredentials
};
var client = new HttpClient(handler);
Если прокси задаёте явно, учётные данные кладут на сторону WebProxy. Во многих клиентских сценариях рекомендуют не отдельные имя и пароль, а учётные данные по умолчанию вошедшего пользователя; это WebProxy.UseDefaultCredentials = true.12
6.3. Проблема 407 у учётной записи службы
Учётная запись процесса важна и здесь. «Учётные данные по умолчанию» — это учётные данные той записи, от которой запущен процесс. Запустите как интерактивного пользователя — к прокси идёт аутентификация от этого пользователя; запустите как службу LocalSystem — от учётной записи компьютера.
- Если прокси аутентифицирует пользователей через Active Directory, учётную запись компьютера или локальную запись он принять не может, и 407 продолжается, как только приложение становится службой
- Наоборот, в некоторых средах на стороне прокси есть исключение аутентификации для служб (по исходному IP или по учётной записи)
Поэтому разбор 407 не закрывается одними «настройками приложения»: это ещё и проверка на стороне инфраструктуры, может ли прокси аутентифицировать учётную запись процесса. Для приложения, которое будет службой, ещё на этапе проектирования стоит выбрать одно из: запускать под доменной учётной записью службы (gMSA и аналоги), сделать исключение аутентификации на стороне прокси или поднять внутренний промежуточный прокси без требования аутентификации.
Есть и способ вписать учётные данные в переменную окружения, как HTTP_PROXY=http://user:pass@proxy:80807, но тогда пароль открытым текстом оказывается в переменной окружения (= в сведениях о процессе), поэтому для постоянной эксплуатации это не рекомендуется.
7. HTTPS и прокси — туннели CONNECT и инспекция TLS
7.1. HTTPS проходит через прокси как «туннель»
Когда для HTTPS используют прокси, клиент сначала отправляет прокси запрос CONNECT целевой-узел:443, и прокси открывает TCP-туннель. При успехе прокси возвращает 200, после чего клиент и сервер назначения выполняют TLS-рукопожатие внутри этого туннеля. Если туннель не открывается, прокси возвращает 407 (нужна аутентификация), 502 или аналог.16
В этой модели прокси не читает содержимое туннеля (зашифрованный HTTPS). В журнале прокси остаются имя узла назначения и успех соединения; путь URL не виден — так ведёт себя прокси без расшифровки.
flowchart TB
accTitle: HTTPS через прокси это туннель CONNECT
accDescr: Клиент отправляет CONNECT прокси, прокси открывает TCP-туннель и возвращает 200, затем клиент и назначение выполняют TLS-рукопожатие в туннеле. Журнал прокси видит узел, не путь URL
cli["Клиент"] -->|"CONNECT host:443"| px["Прокси"]
px -->|"200 и TCP-туннель"| dest["Назначение"]
dest -->|"TLS внутри туннеля"| cli
px -.-> log["Журнал: только узел и успех"]
Рис. 7: Прокси без расшифровки видит узел, не зашифрованный путь.
7.2. Прокси с инспекцией TLS и ошибки сертификата
У продуктов безопасности, с другой стороны, есть тип инспекции TLS (расшифровка SSL, break and inspect): прокси завершает TLS, смотрит содержимое и заново шифрует перед пересылкой. В этой схеме сертификат сервера, который видит клиент, уже не настоящий; его заменяют сертификатом, переподписанным собственным CA прокси.13
Посылка, без которой схема не работает: «сертификат CA прокси раздан в доверенные корневые каждого клиента». На машине, куда он не доехал, или в среде выполнения, которая не смотрит хранилище сертификатов Windows (инструменты со своим хранилищем доверия), проверка сертификата падает. В .NET это обычно проявляется как HttpRequestException с внутренним AuthenticationException (сообщение вроде «the remote certificate is invalid»).
Принципы исправления такие.
- Распространите внутренний сертификат CA в хранилище «Доверенные корневые центры сертификации» локального компьютера. Когда класть в пользовательское хранилище, а когда в хранилище компьютера, разобрано в «Практическое руководство по хранилищу сертификатов Windows».
- Не отключайте проверку сертификатов в коде. Обход, который всегда возвращает true из
ServerCertificateCustomValidationCallback, становится уязвимым приложением: во внешней сети атаку «человек посередине» оно уже не увидит. - Трафик с пиннингом сертификата инспектировать нельзя. Соединения, которые проверяют конкретный сертификат Microsoft, как делают некоторые компоненты Windows, падают в момент, когда прокси подменяет сертификат; обхода кроме исключения нет.4 Для трафика в сторону SaaS вроде Microsoft 365 сама Microsoft рекомендует исключать его из расшифровки и инспекции на сетевом уровне.13
Симптом «все внутренние сайты открываются, а конкретная облачная служба в приложении даёт ошибку сертификата» сначала стоит проверять как сочетание списка исключений инспекции TLS и пиннинга.
flowchart TB
accTitle: Прокси с инспекцией TLS переподписывает сертификат
accDescr: Прокси завершает TLS, проверяет содержимое и предъявляет сертификат, переподписанный собственным CA. Проверка проходит только если этот CA в доверенных корневых. Не отключайте проверку в коде
real["Настоящий сертификат сервера"] --> px["Прокси с инспекцией TLS"]
px --> fake["Переподписан CA прокси"]
fake --> client["Проверка клиента"]
client -->|"CA в доверенных корневых"| ok["Успех"]
client -->|"CA нет"| err["Ошибка сертификата"]
err -.-> fix["Распространить CA в хранилище"]
Рис. 8: Инспекция работает только вместе с распространением внутреннего CA.
8. Диагностика — пять шагов, чтобы найти причину
Разбор «не подключается» ведите механически в этом порядке.
| Шаг | Что делаете | Что узнаёте |
|---|---|---|
| (1) Воспроизвести | Обратиться к проблемному URL через curl.exe -v или Invoke-WebRequest (лучше на той же машине, под той же учётной записью) |
Проблема приложения или среды |
| (2) Снять параметры | Снять три источника: netsh winhttp show proxy, пользовательские параметры и переменные окружения |
Что лежит в каком источнике |
| (3) Определить учётную запись | Определить учётную запись процесса (служба, Планировщик заданий, другой пользователь) | Под какими параметрами и какими учётными данными оно работает |
| (4) Классифицировать ошибку | Различить 407 / 403 / сбой разрешения имени / таймаут / ошибку сертификата | Отделить аутентификацию прокси, отказ политики, маршрут и инспекцию TLS |
| (5) Журнал прокси | Проверить соответствующее время в журнале доступа прокси-сервера | Дошёл ли трафик до прокси вообще и кого он аутентифицировал |
Шаг (2) можно снять разом через PowerShell.
# (1) Пользовательские параметры (WinINET) — читается HKCU учётной записи процесса
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' |
Select-Object ProxyEnable, ProxyServer, ProxyOverride, AutoConfigURL
# (2) Машинные параметры (WinHTTP)
netsh winhttp show proxy
# (3) Переменные окружения
Get-ChildItem env: | Where-Object Name -match 'proxy'
Несколько практических советов.
- В тесте воспроизведения (1) помните, какой источник параметров читает инструмент. Штатный
curl.exeWindows может явно указать прокси через-x http://proxy:8080, а для проверки TLS обычно использует хранилище сертификатов ОС (Schannel).Invoke-WebRequestв Windows PowerShell 5.1 идёт по стороне .NET Framework (по умолчанию параметры интернета); PowerShell 7 — по стороне .NET (сначала переменные окружения). «curl проходит, приложение нет» само по себе намекает на расхождение источников настроек. - Если в (3) цель — служба, перепроверьте (1) и (2) под той же учётной записью, что и служба. Проверка в собственной сессии администратора не доказывает, что видит LocalSystem.
- В классификации ошибки (4) для 407 первым кандидатом берите главу 6 (аутентификация), для ошибки сертификата — главу 7 (инспекция TLS), для таймаута — «до прокси не дошло» (маршрут, разрешение имени, брандмауэр). Случай, когда виновато входящее правило брандмауэра Windows, а не прокси, разобран в «Брандмауэр Windows и бизнес-приложения».
- Если дошли до (5), а в журнале прокси следа нет, трафик до прокси не дошёл. Проверяйте решение DIRECT у PAC, список исключений или забытую переменную окружения и при необходимости подтвердите фактическое назначение захватом пакетов («Практический захват пакетов в Windows — как выбрать pktmon, netsh trace и Wireshark»).
flowchart TB
accTitle: Пять шагов диагностики сбоя прокси
accDescr: Воспроизвести под той же учётной записью, снять три источника параметров, определить учётную запись процесса, классифицировать ошибку, затем проверить журнал прокси
s1["Воспроизвести curl"] --> s2["Снять три источника"]
s2 --> s3["Определить учётную запись"]
s3 --> s4["Классифицировать ошибку"]
s4 --> s5["Проверить журнал прокси"]
s4 -.-> e407["407: аутентификация"]
s4 -.-> ecert["Ошибка сертификата: инспекция"]
s4 -.-> eto["Таймаут: не дошло"]
Рис. 9: Пройдите пять шагов по порядку. Класс ошибки выбирает следующую главу.
9. Рекомендация по проектированию — сделать приложение, в котором прокси можно задать
Переверните процедуру разбора — получите руководство по проектированию на стороне приложения. Для Windows-приложения, которое сдаёте в среду с корпоративным прокси, рекомендуется следующее.
- Сделайте прокси задаваемым из настроек приложения. По умолчанию — «следовать параметрам ОС». В большинстве сред умолчания достаточно; только в исключительных средах — PAC нельзя прочитать, работает как служба, особая конфигурация прокси — дайте возможность указать URL прокси, список исключений и «не использовать прокси» из файла настроек. Точка реализации —
HttpClientHandler.Proxy/UseProxyв разделе 5.3.14 - Зафиксируйте, как внутренние назначения (API, базы данных, серверы лицензий и аналоги) исключаются из прокси. Запишите во внедренческую инструкцию, чем их исключаете: PAC DIRECT, списком исключений или
NO_PROXY. Правила сопоставленияNO_PROXY(без подстановочных знаков, что значит ведущая точка) часто понимают неверно, поэтому приложите примеры.7 - Проектируйте таймауты и повторы в расчёте на проход через прокси. Если прокси лежит или застрял на аутентификации, реализация, которая ждёт длинный таймаут по умолчанию, подвешивает и интерфейс, и эксплуатацию. Отделите более короткий таймаут соединения и ограничьте повторы идемпотентными запросами (детали проектирования в «Не оборачивайте HttpClient в using»).
- Пишите в журнал, какой прокси использовался. Сделайте так, чтобы само приложение могло ответить на первый вопрос разбора сбоя.
Журнал как в пункте 4 уже полезен, если записывает только результат выбора. Суть — вывести маршрут из тех параметров (обработчика), которыми вы реально собрали клиент. Если журналировать HttpClient.DefaultProxy напрямую, запишете значение, расходящееся с фактическим маршрутом, когда обработчик явно указывает Proxy или ставит UseProxy = false.
using System.Net.Http;
// handler — тот же экземпляр, которым создавали HttpClient
// UseProxy=false всегда напрямую. Если есть явное указание — оно, иначе DefaultProxy
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-отправка {Target} маршрут {Route} учётная запись {User}",
target, route, Environment.UserName);
Если при запуске один раз записать «маршрут» и «учётную запись процесса» для основных назначений, шаги (1)–(3) главы 8 заканчиваются чтением журнала. Когда говорят «в браузере работает, а…», уметь ответить со стороны приложения «я использовал эти параметры и этот маршрут» — условие приложения, устойчивого к неприятностям с прокси.
flowchart TB
accTitle: Сделать прокси настраиваемым и журналировать маршрут
accDescr: По умолчанию следовать параметрам ОС, разрешить явный URL прокси или обход или отсутствие прокси из настроек приложения и журналировать фактически использованный маршрут вместе с учётной записью процесса
def["По умолчанию: следовать параметрам ОС"] --> exc{"Исключительная среда?"}
exc -->|"PAC не прочитан / служба / особое"| cfg["Задать URL, исключения или без прокси"]
exc -->|"Обычный случай"| os["Использовать умолчание ОС"]
cfg --> log["Журналировать маршрут и учётную запись"]
os --> log
Рис. 10: Настраивайте, когда нужно. Всегда пишите в журнал, какой маршрут использовался.
10. Итог
- Параметры прокси Windows делятся на три источника — пользовательские параметры WinINET, машинные параметры WinHTTP и переменные окружения — и какой из них читается, решают приложение (его HTTP-стек) и учётная запись процесса.
- WinINET — для интерактивных приложений и в службе не поддерживается; для служб предназначен WinHTTP (
netsh winhttp). Для «вручную работает, как служба — нет» сначала проверяйте, не другая ли учётная запись процесса. netsh winhttp set proxy— статическая настройка: PAC, автоопределение и аутентификация в неё не входят. В сети на PAC нужно заранее решить, как обращаться с клиентами, которые PAC не читают.FindProxyForURLв PAC возвращает прокси или DIRECT в зависимости от URL. WPAD работает только в сети с инфраструктурой DHCP/DNS.- Умолчание .NET Framework — параметры интернета учётной записи процесса (переопределяется
defaultProxy); .NET (Core и новее) — переменные окружения, затем пользовательские параметры прокси. Явное указание (HttpClientHandler.Proxy) всегда наивысший приоритет. - 407 — ошибка аутентификации прокси; в приложении под учётной записью службы типичная причина — «учётные данные по умолчанию» становятся другим лицом.
- Прокси с инспекцией TLS предполагает распространение внутреннего сертификата CA, и правильный ответ на ошибку сертификата — раздача в хранилище сертификатов, а не отключение проверки. Трафику с пиннингом нужно исключение.
- Диагностируйте механически в порядке «воспроизвести → снять три источника параметров → определить учётную запись процесса → классифицировать ошибку → журнал прокси». На стороне приложения лучшая профилактика — проектирование, при котором «прокси можно задать, а использованный маршрут попадает в журнал».
В следующий раз, когда скажут «только бизнес-приложение не подключается», сначала задайте это.
Под какой учётной записью запущено это приложение и какой из трёх источников параметров прокси оно читает?
Один этот вопрос сильно меняет вход в разбор.
Похожие статьи
- Не оборачивайте HttpClient в using ── практика HTTP в бизнес-приложениях на C# (шаблоны создания, таймауты, повторы)
- Практический захват пакетов в Windows — как выбрать pktmon, netsh trace и Wireshark
- Брандмауэр Windows и бизнес-приложения — регистрируйте входящие правила из установщика
- Как создавать и эксплуатировать службы Windows — от выбора между планировщиком заданий и службами до превращения BackgroundService в службу Windows
- NTLM и Kerberos на схемах — почему аутентификация «скатывается» на NTLM
- Практическое руководство по хранилищу сертификатов Windows — пользователь или компьютер, что выбрать?
Смежные области консультирования
KomuraSoft LLC занимается разбором сбоев связи Windows-приложений в средах корпоративного прокси, прокси с аутентификацией и инспекции TLS — «на машине разработчика работает, в сети заказчика не ходит», «после запуска как службы внешний API перестал быть доступен» — и консультациями по проектированию связи бизнес-приложений в расчёте на прокси (пункты настроек, таймауты, журналирование). Можно начать с того, как воспроизвести явление и как снять журналы.
- Разработка приложений для Windows
- Расследование ошибок и причин
- Технические консультации и ревью дизайна
- Связаться с нами
Справочные ссылки
-
Microsoft Learn, WinINet vs. WinHTTP. О рекомендации использовать WinINET, если только процесс не работает внутри службы или служебного процесса, которому нужны олицетворение и изоляция сеансов, и о сравнительной таблице функций: кэш учётных данных, запрос учётных данных, поддержка служб, олицетворение, изоляция сеансов и другое. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, netsh winhttp. О синтаксисе netsh winhttp show/set/import/reset; proxy-server и bypass-list у set proxy; import proxy source=ie; и подробных параметрах прокси в JSON (Proxy, ProxyBypass, AutoconfigUrl, AutoDetect) через set advproxy. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, About WinHTTP. О том, что WinHTTP — HTTP-стек для служб и серверной стороны: умеет работать под учётной записью службы и олицетворять, но не разделяет cookie, кэш, учётные данные браузера и параметры интернета пользователя. ↩ ↩2 ↩3
-
Microsoft Learn, Using a proxy with Delivery Optimization. О том, что netsh winhttp set proxy — статическая настройка без автоопределения, URL PAC и аутентификации прокси; о параметрах прокси на устройство для контекстов без вошедшего пользователя (CSP NetworkProxy, политика «Make proxy settings per-machine»); и о трафике с пиннингом сертификата, который падает при инспекции TLS и нуждается в исключении. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, WinHTTP AutoProxy Support. О том, что скрипт PAC содержит функцию FindProxyForURL(url, host), которая на каждый запрос вычисляет список прокси и особым возвращаемым значением указывает прямое подключение, и о том, что более старый AutoProxy API не встраивает автопрокси в HTTP-стек сам, так что приложение должно вызвать WinHttpGetProxyForUrl. ↩ ↩2 ↩3
-
Microsoft Learn, WinHttpGetProxyForUrl function. О том, что это реализация протокола WPAD, её нужно вызывать по URL, потому что файл PAC может вернуть другой прокси для другого URL, и она поддерживает и явный URL PAC, и автоопределение из сети. ↩ ↩2
-
Microsoft Learn, HttpClient.DefaultProxy Property. О том, что Windows сначала читает переменные окружения HTTP_PROXY, HTTPS_PROXY, ALL_PROXY и NO_PROXY и, если они не заданы, пользовательские параметры прокси; что Linux инициализируется без прокси, если переменных окружения нет; что NO_PROXY не поддерживает подстановочные знаки и сопоставляет поддомен по ведущей точке; и что URL прокси может включать имя пользователя и пароль. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, Configuring Internet Applications. О том, что элемент defaultProxy задаёт прокси по умолчанию в .NET Framework; что HttpWebRequest без свойства Proxy использует прокси по умолчанию; и что системные параметры интернета и файл конфигурации складываются с приоритетом файла конфигурации. ↩ ↩2 ↩3
-
Microsoft Learn, defaultProxy element (network settings). Об атрибутах enabled и useDefaultCredentials элемента system.net/defaultProxy, дочерних элементах proxy, bypasslist и module, о том, что при пустом элементе берутся системные параметры прокси, и о настройке через HttpClient.DefaultProxy при миграции на .NET 6 и новее. ↩ ↩2 ↩3
-
Microsoft Learn, Authentication in WinHTTP. О том, что при необходимости аутентификации прокси возвращаются код состояния 407 и заголовок Proxy-Authenticate (аутентификация сервера — 401 и WWW-Authenticate); о разнице между Basic и схемами «вызов — ответ» вроде Kerberos; и о том, что в схеме «вызов — ответ» имя пользователя и пароль по сети не идут. ↩ ↩2 ↩3
-
Microsoft Learn, HttpClientHandler.DefaultProxyCredentials Property. О свойстве, которое задаёт учётные данные для аутентификации к прокси по умолчанию, когда UseProxy истинно и Proxy равен null, так что используется системный прокси по умолчанию. ↩ ↩2
-
Microsoft Learn, WebProxy.Credentials Property. О том, что свойство Credentials — учётные данные, отправляемые прокси в ответ на HTTP 407, и о рекомендации во многих клиентских сценариях ставить UseDefaultCredentials в true, чтобы использовались учётные данные по умолчанию вошедшего пользователя. ↩ ↩2
-
Microsoft Learn, Understanding implications when using network intermediation to decrypt or manipulate Microsoft 365 traffic at the network layer. О том, что инспекция TLS (расшифровка SSL) — схема, в которой прокси или брандмауэр расшифровывает, проверяет и заново шифрует TLS; что она может вызвать сбой работы и деградацию производительности в службах, рассчитанных на сквозной TLS; и о рекомендации исключать трафик в сторону Microsoft 365 из расшифровки и инспекции на сетевом уровне. ↩ ↩2 ↩3
-
Microsoft Learn, Make HTTP requests with the HttpClient class. О двух способах конфигурации HttpClient.DefaultProxy и HttpClientHandler.Proxy; о том, что указание Proxy важнее файла конфигурации и параметров локального компьютера; о типичной схеме WPAD, когда файл PAC (wpad.dat и аналоги) берут по DNS-имени wpad или через DHCP; и о правиле обхода локальных назначений по короткому имени, loopback и совпадению DNS-суффикса. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, WinHttpOpen function. О значении каждого значения dwAccessType. WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY (Windows 8.1 и новее) сам выбирает прокси из системных/пользовательских параметров и также сам обрабатывает отказоустойчивость и аутентификацию, а WINHTTP_ACCESS_TYPE_DEFAULT_PROXY с 8.1 не рекомендуется. ↩
-
Microsoft Learn, Work with existing on-premises proxy servers. О том, что исходящий HTTPS устанавливается запросом CONNECT к прокси; что успех возвращает HTTP 200; и что ответы вроде 407 (нужна аутентификация) или 502 означают, что прокси связь не разрешает, поэтому разбор стоит продолжать вместе с командой, отвечающей за прокси. ↩
Похожие статьи
Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.
Сеть работает, а Windows пишет «Нет доступа к интернету» — разбираем NCSI, DNS, прокси и VPN
Почему Windows сообщает «Нет доступа к интернету», хотя сеть работает: разбираем решение NCSI о связности. Отделяем DNS, прокси, VPN и ca...
Порядок разрешения имён в Windows — hosts, кэш DNS, LLMNR/mDNS и DoH
Какой слой ответил — hosts, кэш DNS, DNS-сервер или LLMNR/mDNS — решает, почему часть ПК не подключается. Порядок разрешения имён Windows...
Time Travel Debugging — записывать и перематывать ошибки, которые не воспроизводятся в долгоживущих приложениях
Ошибка раз в месяц оставляет в дампе только результат. Записывайте и перематывайте исполнение через WinDbg Time Travel Debugging (TTD): T...
Почему ломаются аргументы ── правила аргументов командной строки Windows
В Windows массива аргументов нет: в CreateProcess уходит одна строка, делит её принимающая сторона. Правила деления CommandLineToArgvW, C...
Окончание драйверов принтера Windows ── как готовить печать форм и этикеток в бизнес-приложениях
Microsoft поэтапно прекращает сопровождение драйверов принтера v3/v4; с июля 2026 IPP class driver предпочтут. Что исчезает в Windows pro...
Связанные темы
Эти страницы показывают тему статьи в более широком контексте услуг и решений.
Технические темы Windows
Раздел о разработке Windows, расследовании сбоев и использовании существующих активов.
Услуги по этой теме
Статья напрямую связана со следующими услугами.
Разработка приложений для Windows
Бизнес-приложения, интеграция оборудования и средства связи — от требований до разработки.
Частые вопросы
Вопросы, которые часто возникают при консультациях по теме статьи.
- Браузер выходит в интернет, а бизнес-приложение не проходит корпоративный прокси. Почему?
- Браузер читает пользовательские параметры прокси WinINET, но бизнес-приложение вовсе не обязательно смотрит туда же. Если оно запущено как служба Windows или под другой учётной записью, оно берёт параметры, видимые этой записи, машинные параметры WinHTTP и переменные окружения. Сначала определите учётную запись процесса и проверьте прокси и командой netsh winhttp show proxy, и в пользовательских параметрах, которые видит эта запись. Если то же самое воспроизводится через curl.exe на той же машине и под той же учётной записью, это не баг приложения, а расхождение источников настроек.
- Я задал netsh winhttp set proxy, но трафик приложения не изменился. Почему?
- netsh winhttp задаёт параметры по умолчанию WinHTTP на уровне компьютера. На браузеры и интерактивные приложения, которые читают WinINET, и на HttpClient в .NET (Core и новее), который сначала смотрит переменные окружения, это не влияет. К тому же netsh winhttp set proxy — статическая настройка: PAC, автоопределение и аутентификация прокси в неё не входят. Сначала выясните, каким HTTP-стеком пользуется приложение и из какого источника оно берёт прокси.
- Какие параметры прокси читает приложение .NET?
- .NET Framework по умолчанию берёт параметры интернета (эквивалент WinINET) той учётной записи, от которой запущен процесс; их можно переопределить элементом system.net/defaultProxy в app.config. HttpClient в .NET (Core и новее) сначала читает HTTP_PROXY, HTTPS_PROXY и NO_PROXY; если они не заданы, переключается на пользовательские параметры прокси Windows. В обоих случаях явный HttpClientHandler.Proxy имеет приоритет. Порядок по умолчанию у Framework и у Core разный, поэтому при миграции поведение прокси нужно проверить заново.
- Что проверять, когда возвращается 407 Proxy Authentication Required?
- 407 означает, что аутентификацию требует сам прокси, а не сервер назначения (это 401). Сначала по заголовку Proxy-Authenticate посмотрите схему (Negotiate, NTLM, Basic), а в .NET передайте учётные данные через HttpClientHandler.DefaultProxyCredentials или WebProxy.UseDefaultCredentials. Если приложение работает под учётной записью службы, «учётные данные по умолчанию» — это уже данные этой службы, поэтому типичный случай: у интерактивного пользователя проходит, а после запуска как службы появляется 407. В журнале прокси дополнительно проверьте, кого он аутентифицировал.
- Прокси с инспекцией TLS даёт ошибки сертификата. Можно ли отключить проверку сертификатов?
- Отключать не рекомендуется. Прокси с инспекцией TLS расшифровывает трафик и предъявляет клиенту сертификат, переподписанный собственным центром сертификации (CA). Если этот сертификат CA нет среди доверенных корневых, проверка падает. Правильное исправление — распространить внутренний сертификат CA в хранилище сертификатов Windows (обычно «Доверенные корневые центры сертификации» локального компьютера). Если отключить проверку в коде, атаку «человек посередине» во внешней сети уже не обнаружить, и уязвимость останется.
Об авторе
Страница с профилем автора статьи.
Го Комура
Представитель KomuraSoft LLC
Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.