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

С# HttpWebRequest SEC_I_RENEGOTIATE Периодические ошибки

Я работаю над функциями входа/выхода с использованием SSL POST-вызовов в приложении С# (.Net framework 3.5). Получение ответа с сервера через HttpWebRequest:: BeginGetResponse() работает 80% времени, но другие 20% периодически перебрасываются:

The request was aborted: Could not create SSL/TLS secure channel.

Я включил трассировку SSL, используя предложенную статью из другого вопроса. Это создало два разных шаблона в запросах.

Похоже, что во время выполнения ошибка:

System.Net Error: 0 : [3680] Decrypt returned SEC_I_RENEGOTIATE.

что вызывает повтор инициализации контекста безопасности. Когда это произойдет, и это будет успешным, вот вывод (отметили, что я пропустил фактический адрес):

System.Net Error: 0 : [3680] Decrypt returned SEC_I_RENEGOTIATE.
System.Net Information: 0 : [3680] InitializeSecurityContext(credential =   System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [3680] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=78, returned code=ContinueNeeded).
System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=1259, returned code=ContinueNeeded).
System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=OK).
System.Net Information: 0 : [7148] Remote certificate: [Version]
  V1

При сбое:

System.Net Error: 0 : [3680] Decrypt returned SEC_I_RENEGOTIATE.
System.Net Information: 0 : [3680] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0ab50, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [3680] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=78, returned code=ContinueNeeded).
System.Net Error: 0 : [3680] Exception in the HttpWebRequest#20730349:: - The request was aborted: Could not create SSL/TLS secure channel.
System.Net Verbose: 0 : [3680] HttpWebRequest#20730349::EndGetResponse()
System.Net Error: 0 : [3680] Exception in the HttpWebRequest#20730349::EndGetResponse - The request was aborted: Could not create SSL/TLS secure channel.

Я могу, конечно, поймать это исключение, но что такое правильная обработка?

Есть ли способ для моего приложения предотвратить (или правильно обработать) эти ошибки? Когда это случается, это кажется постоянной ошибкой какое-то время, но затем снова начинает работать после некоторого неопределенного количества запросов.

Спасибо!

4b9b3361

Ответ 1

(Для исходного ответа см. ниже.)

Обычно эта ошибка означает, что ваш клиент и сервер не настроены на использование одного и того же типа шифрования. Часто самый простой способ его исправления явно устанавливает версию для использования в клиенте.

Если вы используете .NET 4.5 или новее, вот варианты, которые нужно попробовать, чтобы от самого безопасного до наименее безопасного:

  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

Если вы используете .NET 4.0 или старше, вы можете использовать только последнюю строку выше, поскольку эти версии не поддерживают TLSv1.1 и TLSv1.2. Настоятельно рекомендуется обновить до .NET 4.5, чтобы воспользоваться поддержкой TLSv1.2.

В дополнение к настройке свойства SecurityProtocol вам также может потребоваться установить: ServicePointManager.Expect100Continue = true;

Если ни одна из этих настроек не помогает, это, вероятно, означает, что ваш сервер поддерживает только SSLv3 (или, что еще хуже, SSLv2). Если это так, обновите свой сервер! SSLv3 сломан и больше не должен использоваться.


SSLv3 НЕ ДОЛЖЕН считаться безопасным. НЕ используйте эти настройки! Хотя это был правильный ответ в 2011 году, он остается здесь только по историческим причинам.

Перед запросом необходимо добавить следующие строки кода:

ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Из того, что я видел, более старые версии (.NET 2 и/или Windows xp/2003 и старше) использовали их как параметры по умолчанию, но более новые версии (.NET 3 и/или Windows Vista/2008 и новее) не.забастовкa >

Ответ 2

Это не объяснение и не истинное решение: это просто самый прагматичный способ решения этой проблемы, который мы нашли в нашем случае (выполнение SOF-запроса WCF через HTTPS с использованием SSL-сертификата клиента с Apache и Java-сервер).

Catch SecurityNegotiationException и повторить попытку на месте (т.е. вместо того, чтобы перерабатывать сообщение, если используете msmq), и подавить сообщение об исключении в этом случае. Просто включите счетчик производительности или что-то простое, чтобы вы могли отслеживать, становится ли проблема хуже.

В конце концов, это всего лишь одна из тех врожденных проблем, связанных с сетью, с которыми ваш код должен справиться.

Ответ 3

Я думал, что поделился своим опытом, поскольку в последнее время я читал большинство вопросов о стеке:

Другим подходом к этому, который я видел, является рассмотрение HTTP Keep-Alive. В последних версиях .Net он использует HTTP 1.1 по умолчанию, что означает, что Keep-Alive установлен на true и Expect100.

Из моего опыта это создает прилипание ресурсов ниже по течению и не является надежным за балансировщиком нагрузки.

Два варианта

1) Восстановите и повторите попытку, которая кажется слегка вонючей. Однако, как упоминает Khanfx, сетевые проблемы могут возникать ergo: заблуждения сетей. TOPAZ - один из способов решения этой проблемы: https://msdn.microsoft.com/en-us/library/hh680901%28v=pandp.50%29.aspx?f=255&MSPPError=-2147217396

2) Отключите Keep-Alive либо через HttpwebRequest, либо испустив заголовок закрытия соединения, если используете HttpClient.

НТН.