web-dev-qa-db-fra.com

"La connexion sous-jacente a été fermée: une erreur inattendue s'est produite lors d'un envoi." Avec certificat SSL

Problème: je reçois cette exception "LA CONNEXION SOUS-JACENTE A ÉTÉ FERMÉE: UNE ERREUR INATTENDUE SE PRODUIT SUR UN ENVOI" dans mes journaux et brise notre intégration OEM avec notre système de marketing par courrier électronique à des moments aléatoires variant de [1 heure à 4 heures].

Mon site Web est hébergé sur un Windows Server 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, j'envoie un httpWebRequestobject avec toutes les informations d'identification et je récupère 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-JACENTÉE A ÉTÉ FERMÉE: UNE ERREUR INATTENDUE SURVENUE SUR UN ENVOI" et même si le système tente d'obtenir l'URL du httpWebRequest échoue avec la même exception. Le seul moyen de le faire fonctionner à nouveau est de recycler le pool d'applications ou tout élément est modifié dans web.config. Je suis vraiment épuisé toute l'option que je pouvais penser.

Option essayée

Explicitement ajouté, keep-alive = false

keep-alive = true

Augmentation du délai d'attente: <httpRuntime maxRequestLength="2097151" executionTimeout="9999999" enable="true" requestValidationMode="2.0" />

J'ai téléchargé cette page sur un site Web autre que SSL pour vérifier si le certificat SSL de notre serveur de production établit la connexion pour supprimer un peu comment.

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

Code:

Public Function CreateHttpRequestJson(ByVal url) As String
    Try
        Dim result As String = String.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 String = 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.Substring(0, result.Length - 2)
            End Using
        End Using
        Me.midFrame.Attributes("src") = result
    Catch ex As Exception
        objLog.WriteLog("Error:" & ex.Message)
        If (ex.Message.ToString().Contains("Invalid Email")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Email Taken")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Invalid Access Level")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Unsafe Password")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Invalid Password")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().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 [String], ByVal userPassword As [String])
    Dim authInfo As String = Convert.ToString(userName) & ":" & Convert.ToString(userPassword)
    authInfo = Convert.ToBase64String(Encoding.[Default].GetBytes(authInfo))
    request.Headers("Authorization") = "Basic " & authInfo
End Sub`
94
Arvind Morwal

Pour moi c'était tls12:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
159
Lanklaas

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

source: Support TLS 1.2 et .NET: Comment éviter les erreurs de connexion

52
Tochi

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

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls Or SecurityProtocolType.Ssl3
18
Arvind Morwal

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 pouvoir le prendre en charge.

11
aboy021

Cela fait plusieurs jours que je rencontre le même problème avec une intégration qui, elle aussi, "fonctionnait auparavant".

Hors de la dépression, je viens d'essayer

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

Cela a résolu le problème pour moi. Même si l'intégration utilise uniquement SSLv3.

Je me suis rendu compte que quelque chose n'allait pas depuis que Fiddler avait déclaré qu'il existait un "chiffrement de négociation TLS vide" ou quelque chose du genre.

Espérons que cela fonctionne!

9
Medismal

Accédez à votre web.config/App.config pour vérifier le runtime .net que vous utilisez.

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>

Voici la solution:

  1. .NET 4.6 et supérieur. Vous n'avez pas besoin de faire de travail supplémentaire pour prendre en charge TLS 1.2, cela est pris en charge 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 choisir de l'utiliser. Le code suivant rendra TLS 1.2 par défaut, assurez-vous de l'exécuter avant de vous connecter à une ressource sécurisée:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  1. .NET 4.0. TLS 1.2 n’est pas pris en charge, mais si .NET 4.5 (ou une version ultérieure) est installé 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 devons donc utiliser une représentation numérique de cette valeur d’énumération:

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.
8
Guo Huang

J'ai constaté que cela indique que le serveur sur lequel vous déployez du code dispose d'un ancien framework .NET installé qui ne prend pas en charge TLS 1.1 ou TLS 1.2. Étapes à suivre:

  1. Installation du dernier runtime .NET sur vos serveurs de production (IIS et SQL)
  2. Installation du dernier pack de développeurs .NET sur vos machines de développement.
  3. Changez les paramètres "Cadre cible" de vos projets Visual Studio pour le dernier cadre .NET.

Vous pouvez obtenir les derniers .NET Developer Pack et Runtime à partir de cette URL: http://getdotnet.azurewebsites.net/target-dotnet-platforms.html

6
Patrick

Nous avons eu ce problème par 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 de l'envoi".

Leur code était un mélange de .NET 3.x et 2.2, ce qui, si j'ai bien compris, signifie qu'ils utilisent TLS 1.0.

La réponse ci-dessous peut vous aider à diagnostiquer le problème en activant TLS 1.0, SSL 2 et SSL3, mais pour être très clair, vous ne voulez pas le faire à long terme, car ces trois protocoles sont considérés comme peu sûrs et ne doit plus être utilisé:

Pour que notre IIS réponde à leurs appels d'API, nous devions ajouter des paramètres de registre sur le serveur IIS afin d'activer explicitement les versions de TLS - REMARQUE: vous devez redémarrer le serveur Windows (pas uniquement le IIS service) après avoir effectué les modifications suivantes:

[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 cela ne le fait pas, vous pouvez également expérimenter l'ajout de 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 à obliger l’appelant à utiliser TLS 1.2, mais ce qui précède peut aider à diagnostiquer ce problème. c'est 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

Il s'agit d'une version modifiée du script de la page d'aide de Microsoft pour Configurer TLS pour VMM . Cet article basics.net était la page qui m'a donné l'idée de regarder ces paramètres.

3
tomRedox

Il suffit d'ajouter:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

2
M.Qudah

Cela peut être causé par l’utilisation d’un proxy de débogage HTTP, tel que Fiddler.

Je chargeais un certificat PFX à partir d'un fichier local (authentification sur Apple.com) et cela a échoué car Fiddler n'a pas pu transmettre ce certificat.

Essayez de désactiver Fiddler pour vérifier et si telle est la solution, vous devez probablement installer le certificat sur votre ordinateur ou utiliser Fiddler d’une manière ou d’une autre.

1
Simon_Weaver

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;
0
Colonel Software

Vous venez de changer la version de votre application, comme 4.0 à 4.6, et publiez ce code.

Ajoutez également les lignes de code ci-dessous:

httpRequest.ProtocolVersion = HttpVersion.Version10; 
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
0
Viresh

Il aide si quelqu'un, notre problème était avec un certificat manquant. L'environnement est Windows Server 2016 Standard avec .Net 4.6.

Il existe un URI https du service WCF auto-hébergé, pour lequel Service.Open () s'exécuterait sans erreur. Un autre thread continuerait à accéder https: // OurIp: 443/OurService? Wsdl afin de s’assurer que le service était disponible. L'accès au WSDL utilisé pour échouer avec:

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

L'utilisation de ServicePointManager.SecurityProtocol avec les paramètres applicables ne fonctionnait pas. Jouer avec les rôles de serveur et les fonctionnalités n'a pas aidé non plus. Puis, intervenez Jaise George , le SE, résolvant le problème en quelques minutes. Jaise a installé un certificat auto-signé dans IIS, corrigeant le problème. Voici ce qu'il a fait pour résoudre le problème:

(1) Ouvrez IIS manager (inetmgr) (2) Cliquez sur le nœud du serveur dans le panneau de gauche, puis double-cliquez sur "Certificats de serveur". (3) Cliquez sur "Créer un certificat auto-signé" dans le panneau de droite et tapez ce que vous voulez comme nom convivial. (4) Cliquez sur "Site Web par défaut" dans le panneau de gauche, cliquez sur "Liaisons" dans le panneau de droite, cliquez sur "Ajouter", sélectionnez "https", sélectionnez le certificat que vous venez de créer, puis cliquez sur "OK". (5) Accès l'URL https, il devrait être accessible.

0
DiligentKarma