Подтвердить что ты не робот

Что делает этот HTTPS WebRequest тайм-аут, даже если он работает в браузере?

Здесь мой запрос:

var request = (HttpWebRequest) WebRequest.Create("https://mtgox.com/");
request.CookieContainer = new CookieContainer();
request.AllowAutoRedirect = false;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";
request.Headers[HttpRequestHeader.AcceptLanguage] = "en-gb,en;q=0.5";
request.Headers[HttpRequestHeader.AcceptCharset] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7";
request.Timeout = 5000;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
request.Method = "GET";

request.GetResponse();

Заголовки были скопированы из Firefox с использованием HttpFox. Я использовал Fiddler2 для проверки того, что, по крайней мере, для HTTP-запросов, заголовки полностью идентичны между запросами Firefox и моими запросами.

Однако при выполнении запроса на этот конкретный веб-сайт с использованием HTTPS запрос просто отключается. Он работает для других веб-сайтов.

Я должен выполнять его по-другому в Firefox, потому что он всегда работает в Firefox. Однако я не могу отлаживать его с помощью Fiddler2, потому что всякий раз, когда Fiddler2 пересылает эти запросы, они также время, даже когда они создаются Firefox.

Это действительно плохой веб-сайт? Какая часть из вышеперечисленного дает мне прочь как не Firefox?

4b9b3361

Ответ 1

Используя Microsoft Network Monitor, я обнаружил, что HttpWebRequest застрял на этапе, на котором он должен был отправить клиентский ключ обмена ключами. Это просто не было. Сервер должным образом ждал его, но он так и не появился.

Что исправлено, он заставлял HttpWebRequest использовать SSL3 вместо TLS (хотя TLS должен автоматически переходить на SSL3, если необходимо):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Почему это так, я думаю, я никогда не узнаю - только одна из тех таинственных вещей, на которые потребуется больше времени, чем кто-либо, кого я знаю, готов потратить...

Одна вещь, которая отличалась от захватов: вариант TLS имел запись "Alert" в ответе сервера Hello, которая отсутствует в обмене SSL3, а также от всех обменов TLS, которые действительно работали. Любопытно, однако, одно и то же предупреждение присутствует в захвате Firefox, выполняющем запрос успешно.

Наконец, похоже, что был временный сбой OCSP, только когда я впервые опубликовал этот вопрос, который с тех пор был разрешен. Это добавилось в беспорядок, но это не основная проблема.

Ответ 2

В .NET Framework на Windows 7 реализовано расширение TLS: указатель имени сервера (RFC4366). Согласно вашему сообщению Что означает это оповещение TLS, сервер отвечает "Unrecognized Name". Не знаете, почему сообщение сообщается в тайм-аут, потому что это действительно не так. Трассировки сети должны показать, что клиент инициирует завершение соединения после этого [FIN, ACK]. Переход на SSL3 позволяет избежать вызова SNI.

FYI: та же платформа .NET в Windows XP не использует расширение TLS Server Name Indication Extension. Ваша программа будет работать там...

В моем случае я проследил появление этого в отсутствующей директиве ServerName в Apache. Добавление ServerName в конфигурацию SSL решило его, потому что теперь веб-сервер больше не знает своего имени.

Ответ 3

Типичная причина ошибок таймаута с вызовами HttpWebRequest/HttpWebReponse - это "не закрытие объекта ответа/потока", которые поддерживают активные соединения. Вы должны просто закрыть объект Stream или объект HttpWebResponse после прочтения содержимого потока. Ограничение по умолчанию - 2.

HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
string responseString = ((TextReader)new StreamReader(stream)).ReadToEnd();
webResponse.Close();

В качестве альтернативы, если вы внедрили свою логику в веб-службу, которая будет одновременно вызываться многими пользователями, вам может потребоваться увеличить ограничение соединения в объекте HttpWebRequest.

HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);    
webRequest.ServicePoint.ConnectionLimit = 20;

Ответ 4

Недавно узнал об этой же проблеме и захотелось проверить, удалось ли Microsoft установить это в новых версиях .net. Это код, который я тестировал (домен удален для конфиденциальности):

HttpWebRequest request =
    (HttpWebRequest)WebRequest.Create("https://www.xxSomeDomainNamexx.com/");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
Console.WriteLine(reader.ReadToEnd());

Скомпилировано это для .net версий 2.0, 3.0 и 3.5, и все, казалось, демонстрировали то же самое поведение, что и все, что обсуждалось здесь. Затем я попытался выполнить компиляцию с 4.0 и 4.5 и получил правильные ответы в обоих местах.

Исходя из этого, похоже, Microsoft, скорее всего, исправила эту проблему в новых версиях .net. Для потомков я также проверил изменение SecurityProtocol, предложенное enverpex, и он отлично работал на 2.0, 3.0 и 3.5.

Ответ 5

У меня была такая же проблема с тайм-аутом с запросами https, и ни один из ответов не помог мне. Только сейчас я нашел решение, которое разрешило проблему для меня. Обратите внимание, что это работает только с .net framework 4.5 или выше.

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var response = WebRequest.Create("https://yoursecurewebservice").GetResponse();
var body = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(body);

Ответ 6

Скорее всего, клиент HTTPS не может проверить цепочку сертификатов, представленную этим сервером, например, из-за отсутствия корневого сертификата или недоступного ответчика OCSP. То есть может быть что-то другое настроенное в браузере и в клиенте HTTPS, который вы используете.

В качестве одного из вариантов вы можете взять пробную версию нашего HTTPBlackbox и попытаться подключиться с помощью TElHTTPSClient. Он даст вам подробную информацию об ошибках (в случае ошибки), чтобы вы могли определить, что не так с HttpWebRequest.