Я должен ответить на это сам, так как эта проблема имеет простую причину, но очень запутанные симптомы.
Основная причина:
DNS сообщает только адреса IPv4 для хостакогда система не подключена к VPN.Все адреса IPv4 могут использоваться.
Когда VPN-соединение активно, DNS возвращает адреса IPv6 в дополнение к IPv4.Адреса IPv4 по-прежнему доступны, а IPv6 - нет.
Причиной такой неверной конфигурации сети по-прежнему остается загадка, которая заслуживает отдельного поста.
Запутанная часть:
Некоторые приложения работают независимо от состояния VPN-соединения.
«Но веб-браузер может подключаться к одному и тому же хосту с VPN или без нее».Правда.Браузеры могут использовать подход Happy eyeballs , пытаясь подключиться одновременно по IPv4 и IPv6.
«Но у моего старого приложения нет проблем с подключением».Тоже верно.Некоторые старые и не очень старые приложения по умолчанию используют протокол IPv4.Поддержка IPv6 или IPv4 + IPv6 должна быть явно реализована.
«Но иногда это работает».Это происходит, когда VPN-соединения ненадежны.Это приводит ко всевозможным решениям, которые являются простым совпадением.
Что именно происходит:
HttpClient.GetAsync () использует разрешение DNS по умолчанию и может подключаться с использованием обоих IPv4и адреса IPv6.Он не различает и не имеет прямого способа повлиять на выбор протокола.Если DNS возвращает недоступный адрес, HttpClient может использовать этот неверный адрес для подключения, что приводит к тайм-ауту.
Возможные обходные пути:
Лучше всего: попросить ИТ-специалистов устранить проблемы DNS IPv6.DNS не должен сообщать о недоступных адресах.
Хорошо: внедрить Подход "Счастливые глаза" .Подключайтесь к адресам хоста IPv6 и IPv4 с помощью числового IP вместо автоматического разрешения с использованием имени хоста.
OK: всегда подключайтесь к IPv4 с использованием числового IP.
Вот фрагмент кода, который показывает, какдля подключения к определенному IP-адресу:
// Get DNS entries for the host.
var hostEntry = Dns.GetHostEntry(uri.Host);
// Get IPv4 address
var ip4 = hostEntry.AddressList.First(addr => addr.AddressFamily == AddressFamily.InterNetwork);
// Build URI with numeric IPv4
var uriBuilderIP4 = new UriBuilder(uri);
uriBuilderIP4.Host = ip4.ToString());
var uri4 = uriBuilder4.Uri;
// Get IPv6 address
var ip6 = hostEntry.AddressList.First(addr => addr.AddressFamily == AddressFamily.InterNetworkV6);
// Build URI with numeric IPv6
var uriBuilderIP6 = new UriBuilder(uri);
uriBuilderIP6.Host = $"[{ip6}]";
var uri6 = uriBuilder6.Uri;
Для соединений HTTPS числовые адреса работают только с заголовком «host» с именем хоста (не IP-адресом) в нем.Вот способ добавить это.
var client = new HttpClient();
// Add "host" header with real host name e.g. stackoverflow.com
client.DefaultRequestHeaders.Add("Host", uri.Host);