"The underlying connection was closed: An unexpected error occurred on a send." With SSL Certificate

SslConnection

Ssl Problem Overview


Issue

I get this exception

> The underlying connection was closed: An unexpected error occurred on a send.

in my logs, and it is breaking our OEM integration with our e-mail marketing system at random times. (varying from 1-4 hours)

My website is hosted on a Windows Server 2008 R2 with IIS 7.5.7600.

This website has a large number of OEM components, and comprehensive dashboard. Everything works fine with all the other elements of the website except with one of our e-mail marketing component which we are using as an iframe solution within our dashboard.

The way it works is, I send a HttpWebRequest object with all the credentials, and I get a url back which I put in an iframe and it works.

But it only works for some time (1-4 hours), and then from the call to

> webRequest.GetResponse();

I get the exception

> The underlying connection was closed: An unexpected error occurred on a send.

Even if the system tries to get the URL from the httpWebRequest it fails with the same exception.

The only way to make it work again is:

  • to recycle the application pool
  • anything is edited in web.config.

I am really exhausted all the option that i could think of.

Options tried

Explicitly added,

  • keep-alive = false

  • keep-alive = true

  • Increased the time out:

    <httpRuntime maxRequestLength="2097151" executionTimeout="9999999" enable="true" requestValidationMode="2.0" />

I have uploaded this page to a non SSL website to check if the SSL certificate on our production server is making the connection to drop some how.

Any direction toward resolution is greatly appreciated.

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

Ssl Solutions


Solution 1 - Ssl

For me it was tls12:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Solution 2 - Ssl

If you are stuck with .Net 4.0 and the target site is using TLS 1.2, you need the following line instead. ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

source: TLS 1.2 and .NET Support: How to Avoid Connection Errors

Solution 3 - Ssl

The code below resolved the issue

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls Or SecurityProtocolType.Ssl3

Solution 4 - Ssl

Go to your web.config/App.config to verify which .net runtime you are using

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

Here is the solution:

  1. .NET 4.6 and above. You don’t need to do any additional work to support TLS 1.2, it’s supported by default.

  2. .NET 4.5. TLS 1.2 is supported, but it’s not a default protocol. You need to opt-in to use it. The following code will make TLS 1.2 default, make sure to execute it before making a connection to secured resource:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  1. .NET 4.0. TLS 1.2 is not supported, but if you have .NET 4.5 (or above) installed on the system then you still can opt in for TLS 1.2 even if your application framework doesn’t support it. The only problem is that SecurityProtocolType in .NET 4.0 doesn’t have an entry for TLS1.2, so we’d have to use a numerical representation of this enum value:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

  1. .NET 3.5 or below. TLS 1.2 is not supported (*) and there is no workaround. Upgrade your application to more recent version of the framework.

Solution 5 - Ssl

I've been having the same issue for days now with an integration that also just "used to work before".

Out of sheer depression, I just tried

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

This solved it for me..even though the integration strictly only makes use of SSLv3.

I came to the realization that something if off since Fiddler reported saying that there is an "empty TLS negotiation cipher" or something of the like.

Hopefully it works!

Solution 6 - Ssl

In my case the site that I'm connecting to has upgraded to TLS 1.2. As a result I had to install .net 4.5.2 on my web server in order to support it.

Solution 7 - Ssl

I've found that this is a sign that the server where you're deploying code has an old .NET framework installed that doesn't support TLS 1.1 or TLS 1.2. Steps to fix:

  1. Installing the latest .NET Runtime on your production servers (IIS & SQL)
  2. Installing the latest .NET Developer Pack on your development machines.
  3. Change the "Target framework" settings in your Visual Studio projects to the latest .NET framework.

You can get the latest .NET Developer Pack and Runtime from this URL: http://getdotnet.azurewebsites.net/target-dotnet-platforms.html

Solution 8 - Ssl

Just add:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Solution 9 - Ssl

We had this issue whereby a website that was accessing our API was getting the “The underlying connection was closed: An unexpected error occurred on a send.” message.

Their code was a mix of .NET 3.x and 2.2, which as I understand it means they are using TLS 1.0.

The answer below can help you diagnose the issue by enabling TLS 1.0, SSL 2 and SSL3, but to be very clear, you do not want to do that long-term as all three of those protocols are regarded as insecure and should no longer be used:

To get our IIS to respond to their API calls we had to add registry settings on the IIS's server to explicitly enable versions of TLS - NOTE: You have to restart the Windows server (not just the IIS service) after making these changes:

[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

If that doesn't do it, you could also experiment with adding the entry for 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

To be clear, this is not a nice solution, and the right solution is to get the caller to use TLS 1.2, but the above can help diagnose that this is the issue.

You can speed adding those reg entries up with this powershell script:

$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

That's a modified version of the script from the Microsoft help page for Set up TLS for VMM. This basics.net article was the page that originally gave me the idea to look at these settings.

Solution 10 - Ssl

It if helps someone, ours was an issue with missing certificate. Environment is Windows Server 2016 Standard with .Net 4.6.

There is a self hosted WCF service https URI, for which Service.Open() would execute without errors. Another thread would keep accessing https://OurIp:443/OurService?wsdl to ensure that the service was available. Accessing the WSDL used to fail with:

The underlying connection was closed: An unexpected error occurred on a send.

Using ServicePointManager.SecurityProtocol with applicable settings did not work. Playing with server roles and features did not help either. Then stepped in Jaise George, the SE, resolving the issue in a couple of minutes. Jaise installed a self signed certificate in the IIS, poofing the issue. This is what he did to address the issue:

(1) Open IIS manager (inetmgr) (2) Click on the server node in the left panel, and double click "Server certificates". (3) Click on "Create Self-Signed Certificate" on the right panel and type in anything you want for the friendly name. (4) Click on “Default Web site” in the left panel, click "Bindings" on the right panel, click "Add", select "https", select the certificate you just created, and click "OK" (5) Access the https URL, it should be accessible.

Solution 11 - Ssl

You just change your application version like 4.0 to 4.6 and publish those code.

Also add below code lines:

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

Solution 12 - Ssl

I found Solution by updating web.config with below code.

My .Net Framwork was set to 4.0 and after organization level TLS protocol update I suddenly started facing this issue. So I referred above answer of "Guo Huang" and updated the targetFramework and it worked.

<system.web>
		<compilation debug="true" targetFramework="4.7.2" />
		<httpRuntime targetFramework="4.7.2"  maxRequestLength="102400" executionTimeout="3600"/>
</system.web>

Solution 13 - Ssl

Using a HTTP debugging proxy can cause this - such as Fiddler.

I was loading a PFX certificate from a local file (authentication to Apple.com) and it failed because Fiddler wasn't able to pass this certificate on.

Try disabling Fiddler to check and if that is the solution then you need to probably install the certificate on your machine or in some way that Fiddler can use it.

Solution 14 - Ssl

The below code solved my problem :

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArvind MorwalView Question on Stackoverflow
Solution 1 - SslLanklaasView Answer on Stackoverflow
Solution 2 - SslTochiView Answer on Stackoverflow
Solution 3 - SslArvind MorwalView Answer on Stackoverflow
Solution 4 - SslGuo HuangView Answer on Stackoverflow
Solution 5 - SslMedismalView Answer on Stackoverflow
Solution 6 - Sslaboy021View Answer on Stackoverflow
Solution 7 - SslPatrickView Answer on Stackoverflow
Solution 8 - SslM.QudahView Answer on Stackoverflow
Solution 9 - SsltomRedoxView Answer on Stackoverflow
Solution 10 - SslDiligentKarmaView Answer on Stackoverflow
Solution 11 - SslVireshView Answer on Stackoverflow
Solution 12 - SslShirishView Answer on Stackoverflow
Solution 13 - SslSimon_WeaverView Answer on Stackoverflow
Solution 14 - SslColonel SoftwareView Answer on Stackoverflow