“La connexion sous-jacente a été fermée: une erreur inattendue s’est produite lors d’un envoi.”

Problème: j’obtiens cette exception: «LA CONNEXION SOUS-JACENTE A ÉTÉ FERMÉE: UNE ERREUR INATTENDUE EST SURVOLUE EN EXPÉDITION» dans nos journaux et brise notre intégration OEM avec notre système d’e-mail marketing à des moments aléatoires variant de [1 heure à 4 heures]

Mon site Web est hébergé sur un serveur Windows 2008 R2 avec IIS 7.5.7600. Ce site Web contient un grand nombre de composants OEM et un tableau de bord complet. Tout fonctionne bien avec tous les autres éléments du site Web, à l’exception de l’un de nos composants de marketing par courriel que nous utilisons comme solution iframe dans notre tableau de bord. La façon dont cela fonctionne est, je envoie un httpWebRequestobject avec toutes les informations d’identification et je reçois une URL que je mets dans un iframe et cela fonctionne. Mais cela ne fonctionne que pendant un certain temps [1 heure – 4 heures] et puis j’obtiens l’exception ci-dessous “LA CONNEXION SOUS-JACENTE A ÉTÉ FERMÉE: UNE ERREUR INATTENDUE SURPUIT UN ENVOI” et même si le système tente d’obtenir l’URL httpWebRequest échoue avec la même exception. La seule façon de le faire fonctionner à nouveau est de recycler le pool d’applications ou tout ce qui est édité dans web.config. Je suis vraiment épuisé toutes les options auxquelles je pourrais penser.

Option essayée

Explicitly added, keep-alive = false

keep-alive = true

Augmentation du délai d’expiration:

J’ai téléchargé cette page sur un site Web non SSL pour vérifier si le certificate SSL sur notre serveur de production établit la connexion pour en supprimer.

Toute direction vers la résolution est grandement appréciée.

Code:

 Public Function CreateHttpRequestJson(ByVal url) As Ssortingng Try Dim result As Ssortingng = Ssortingng.Empty Dim httpWebRequest = DirectCast(WebRequest.Create("https://api.xxxxxxxxxxx.com/api/v3/externalsession.json"), HttpWebRequest) httpWebRequest.ContentType = "text/json" httpWebRequest.Method = "PUT" httpWebRequest.ContentType = "application/x-www-form-urlencoded" httpWebRequest.KeepAlive = False 'ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 'TODO change the integratorID to the serviceproviders account Id, useremail Using streamWriter = New StreamWriter(httpWebRequest.GetRequestStream()) Dim json As Ssortingng = New JavaScriptSerializer().Serialize(New With { _ Key .Email = useremail, _ Key .Chrome = "None", _ Key .Url = url, _ Key .IntegratorID = userIntegratorID, _ Key .ClientID = clientIdGlobal _ }) 'TODO move it to the web.config, Following API Key is holonis accounts API Key SetBasicAuthHeader(httpWebRequest, holonisApiKey, "") streamWriter.Write(json) streamWriter.Flush() streamWriter.Close() Dim httpResponse = DirectCast(httpWebRequest.GetResponse(), HttpWebResponse) Using streamReader = New StreamReader(httpResponse.GetResponseStream()) result = streamReader.ReadToEnd() result = result.Split(New [Char]() {":"})(2) result = "https:" & result.Subssortingng(0, result.Length - 2) End Using End Using Me.midFrame.Atsortingbutes("src") = result Catch ex As Exception objLog.WriteLog("Error:" & ex.Message) If (ex.Message.ToSsortingng().Contains("Invalid Email")) Then 'TODO Show message on UI ElseIf (ex.Message.ToSsortingng().Contains("Email Taken")) Then 'TODO Show message on UI ElseIf (ex.Message.ToSsortingng().Contains("Invalid Access Level")) Then 'TODO Show message on UI ElseIf (ex.Message.ToSsortingng().Contains("Unsafe Password")) Then 'TODO Show message on UI ElseIf (ex.Message.ToSsortingng().Contains("Invalid Password")) Then 'TODO Show message on UI ElseIf (ex.Message.ToSsortingng().Contains("Empty Person Name")) Then 'TODO Show message on UI End If End Try End Function Public Sub SetBasicAuthHeader(ByVal request As WebRequest, ByVal userName As [Ssortingng], ByVal userPassword As [Ssortingng]) Dim authInfo As Ssortingng = Convert.ToSsortingng(userName) & ":" & Convert.ToSsortingng(userPassword) authInfo = Convert.ToBase64Ssortingng(Encoding.[Default].GetBytes(authInfo)) request.Headers("Authorization") = "Basic " & authInfo End Sub` 

Pour moi c’était tls12:

 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 

Si vous êtes bloqué avec .Net 4.0 et que le site cible utilise TLS 1.2, vous avez besoin de la ligne suivante. ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

source: Prise en charge de TLS 1.2 et .NET: Comment éviter les erreurs de connexion

Le code ci-dessous a résolu le problème

 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls Or SecurityProtocolType.Ssl3 

Dans mon cas, le site auquel je me connecte a été mis à niveau vers TLS 1.2. En conséquence, j’ai dû installer .net 4.5.2 sur mon serveur Web pour le supporter.

J’ai constaté que c’est un signe que le serveur sur lequel vous déployez le code a un ancien framework .NET installé qui ne prend pas en charge TLS 1.1 ou TLS 1.2. Étapes à suivre pour corriger:

  1. Installation de la dernière version de .NET Runtime sur vos serveurs de production (IIS et SQL)
  2. Installer le dernier .NET Developer Pack sur vos machines de développement.
  3. Modifiez les parameters “Target framework” dans vos projets Visual Studio pour les derniers framework .NET.

Vous pouvez obtenir la dernière version du .NET Developer Pack et du Runtime à partir de cette URL: http://getdotnet.azureewebsites.net/target-dotnet-platforms.html

Cela fait plusieurs jours que je rencontre le même problème avec une intégration qui ne fonctionnait plus qu’avant.

Par pure dépression, j’ai juste essayé

 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3; 

Cela a résolu le problème pour moi … même si l’intégration ne fait qu’utiliser uniquement SSLv3.

Je me suis rendu compte que quelque chose s’arrêtait puisque Fiddler avait déclaré qu’il y avait un “chiffre de négociation TLS vide” ou quelque chose du genre.

J’espère que ça marche!

Accédez à votre site web.config / App.config pour vérifier quel environnement d’exécution .net vous utilisez

     

Voici la solution:

  1. .NET 4.6 et supérieur. Vous n’avez pas besoin de faire plus de travail pour supporter TLS 1.2, il est supporté par défaut.

  2. .NET 4.5. TLS 1.2 est pris en charge, mais ce n’est pas un protocole par défaut. Vous devez vous inscrire pour l’utiliser. Le code suivant rendra TLS 1.2 par défaut, assurez-vous de l’exécuter avant d’établir une connexion à une ressource sécurisée:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  1. .NET 4.0. TLS 1.2 n’est pas pris en charge, mais si vous avez installé .NET 4.5 (ou version ultérieure) sur le système, vous pouvez toujours choisir TLS 1.2 même si votre infrastructure d’application ne le prend pas en charge. Le seul problème est que SecurityProtocolType dans .NET 4.0 n’a pas d’entrée pour TLS1.2, nous devrions donc utiliser une représentation numérique de cette valeur enum:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

  1. .NET 3.5 ou inférieur. TLS 1.2 n’est pas pris en charge (*) et il n’y a pas de solution de contournement. Mettez à niveau votre application vers une version plus récente du framework.

Nous avions ce problème dans lequel un site Web qui accédait à notre API recevait le message «La connexion sous-jacente était fermée: une erreur inattendue s’est produite lors d’un envoi».

Leur code était un mélange de .NET 3.x et de 2.2, ce qui, si je comprends bien, signifie qu’ils utilisent TLS 1.0.

Pour que nos services Internet (IIS) répondent à leurs appels d’API, nous avons dû append des parameters de registre sur le serveur IIS pour activer explicitement les versions de TLS. REMARQUE: vous devez redémarrer le serveur Windows après avoir effectué ces modifications:

 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 

Si ce n’est pas le cas, vous pouvez également essayer d’append l’entrée pour SSL 2.0:

 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001 

Pour être clair, ce n’est pas une solution intéressante, et la bonne solution consiste à demander à l’appelant d’utiliser TLS 1.2, mais ce qui précède peut vous aider à identifier le problème.

Vous pouvez accélérer l’ajout de ces entrées reg avec ce script powershell:

 $ProtocolList = @("SSL 2.0","SSL 3.0","TLS 1.0", "TLS 1.1", "TLS 1.2") $ProtocolSubKeyList = @("Client", "Server") $DisabledByDefault = "DisabledByDefault" $Enabled = "Enabled" $registryPath = "HKLM:\\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\" foreach($Protocol in $ProtocolList) { Write-Host " In 1st For loop" foreach($key in $ProtocolSubKeyList) { $currentRegPath = $registryPath + $Protocol + "\" + $key Write-Host " Current Registry Path $currentRegPath" if(!(Test-Path $currentRegPath)) { Write-Host "creating the registry" New-Item -Path $currentRegPath -Force | out-Null } Write-Host "Adding protocol" New-ItemProperty -Path $currentRegPath -Name $DisabledByDefault -Value "0" -PropertyType DWORD -Force | Out-Null New-ItemProperty -Path $currentRegPath -Name $Enabled -Value "1" -PropertyType DWORD -Force | Out-Null } } Exit 0 

C’est une version modifiée du script à partir de la page d’aide Microsoft pour Configurer TLS pour VMM . Cet article de baseics.net était la page qui m’a donné l’idée de regarder ces parameters.

L’utilisation d’un proxy de débogage HTTP peut provoquer cela, comme Fiddler.

Je chargeais un certificate PFX d’un fichier local (authentification sur Apple.com) et il a échoué car Fiddler n’a pas réussi à passer ce certificate.

Essayez de désactiver Fiddler pour vérifier et si c’est la solution, vous devez probablement installer le certificate sur votre ordinateur ou d’une manière quelconque que Fiddler peut l’utiliser.

Le code ci-dessous a résolu mon problème:

 request.ProtocolVersion = HttpVersion.Version10; // THIS DOES THE TRICK ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;