99

I'm trying to establish SSL/TLS connection to test server with self-signed certificate. Communication through unsecure channel worked without issues.

Here is my sample code, which I've written based on this solutions: Allowing Untrusted SSL Certificates with HttpClient C# Ignore certificate errors? .NET client connecting to ssl Web API

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

var c = new HttpClient();
var r = c.GetAsync("https://10.3.0.1:8443/rest/v1").Result;
if (r.IsSuccessStatusCode)
{
    Log.AddMessage(r.Content.Get<string>());
}
else
{
    Log.AddMessage(string.Format("{0} ({1})", (int)r.StatusCode, r.ReasonPhrase));
}

also tried this:

var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = delegate { return true; };
var c = new HttpClient(handler);
...

and this

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

but each time I've got an exception:

InnerException: System.Net.Http.HttpRequestException
   _HResult=-2146233088
   _message=An error occurred while sending the request.
   HResult=-2146233088
   IsTransient=false
   Message=An error occurred while sending the request.
   InnerException: System.Net.WebException
        _HResult=-2146233079
        _message=The request was aborted: Could not create SSL/TLS secure channel.
        HResult=-2146233079
        IsTransient=false
        Message=The request was aborted: Could not create SSL/TLS secure channel.
        Source=System
        StackTrace:
             at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
             at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
        InnerException: 

What do I do wrong? Why I can't connect to this server (which has invalid-self-signed certificate)

Marcin Konrad Ceglarek
  • 1,442
  • 2
  • 13
  • 20

10 Answers10

198

You are doing it right with ServerCertificateValidationCallback. This is not the problem you are facing. The problem you are facing is most likely the version of SSL/TLS protocol.

For example, if your server offers only SSLv3 and TLSv10 and your client needs TLSv12 then you will receive this error message. What you need to do is to make sure that both client and server have a common protocol version supported.

When I need a client that is able to connect to as many servers as possible (rather than to be as secure as possible) I use this (together with setting the validation callback):

  ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Wapac
  • 4,058
  • 2
  • 20
  • 33
  • 1
    I have a similar issue. Because of the POODLE-attack we are forced to shut down TLS 1.0 on our server. When I do this, a third-party app stops working. Decompiling the assambly shows a code similar to yours. It uses webclientc.SendAsync instead of GetAsync. If I copy the code to a consoleapp for testing I can reproduce the error, and by adding ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 it works. I tought that there would be some kind of handshake between server and Client to uncover what TLS version to use? Why doesn't it automatically choose 1.1 when 1.0 is disabled? – Engern Apr 04 '16 at 14:50
  • Note that recommended version is TLS 1.2. And yes, if both sides have enabled certain protocol version, it will be used, but if one side only supports protocols and versions that are not supported by the other side, the connection can't be established. In order to make sure that the app will work, you should explicitly set `ServicePointManager.SecurityProtocol` on both sides because as MSDN tells us, the default value can be different for each machine depending on its software and configuration. – Wapac Apr 05 '16 at 12:28
  • Awesome answer! I had trouble when I switched from PayPal's live url to sandbox which seems to use a different security protocol. Use this answer when using PayPal sandbox. – Mark Ibanez May 25 '16 at 10:35
  • 4
    Thanks! Was struggling 3 hours with this. Adding this line did it for me: `ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;` – Thomas T Jun 10 '16 at 10:31
  • This is the ONLY solution that works with EBay API (api.ebay.com) - I have been searching for a solution for over 6 months, until I found this answer. – Aviad P. Jul 12 '16 at 05:47
  • Sorry, although the situation has improved, the exception still occurs with the EBay API... I was too quick to celebrate. – Aviad P. Jul 12 '16 at 08:28
  • 2
    Note that newer version of .NET has this enabled by default, all we needed to do is to set .NET version to 4.6.1 – martinh_kentico May 01 '17 at 20:31
  • I recently [ran this](https://www.ssllabs.com/ssltest) on our IIS which identified three serious security loopholes. After I fixed all of them, including POODLE attack and less TLS protocols allowed, I started having the issue with a Xamarin App from Android tablets. While this solution helped to fix the `WebClient`-related source code of those apps, how is it safe to blindly return true to `ServerCertificateValidationCallback`? Does that not mean to wildcard-accept any certificate whether valid or not? – Cee McSharpface Sep 04 '17 at 17:14
  • 1
    It means exactly that, valid or not, you don't care. That callback allows you to simply avoid any security checks on that certificate. – Wapac Sep 04 '17 at 19:22
  • 1
    Great answer, I feel like this `ServicePointManager.SecurityProtocol` value should maybe be the default. Or at least that there should be more insight directly inside the thrown Exception. – Chad Nov 12 '19 at 15:11
  • I got this type of error. "message": "The SSL connection could not be established, see inner exception.", – Akash Limbani Apr 01 '20 at 10:09
34

We have been solving the same problem just today, and all you need to do is to increase the runtime version of .NET

4.5.2 didn't work for us with the above problem, while 4.6.1 was OK

If you need to keep the .NET version, then set

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
martinh_kentico
  • 913
  • 7
  • 17
  • 1
    Which of the variants you used and how exactly? – martinh_kentico Jun 27 '17 at 10:21
  • 1
    I have a .NET 4.5 application that starting from today, won't work with a specific SSL site. If I change to 4.6.1 it works fine, but I can't really change. I'm not sure what is there to be done :| – Tsury Sep 12 '17 at 21:04
17

Just as a follow up for anyone still running into this – I had added the ServicePointManager.SecurityProfile options as noted in the solution:

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

And yet I continued to get the same “The request was aborted: Could not create SSL/TLS secure channel” error. I was attempting to connect to some older voice servers with HTTPS SOAP API interfaces (i.e. voice mail, IP phone systems etc… installed years ago). These only support SSL3 connections as they were last updated years ago.

One would think including SSl3 in the list of SecurityProtocols would do the trick here, but it didn’t. The only way I could force the connection was to include ONLY the Ssl3 protocol and no others:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Then the connection goes through – seems like a bug to me but this didn’t start throwing errors until recently on tools I provide for these servers that have been out there for years – I believe Microsoft has started rolling out system changes that have updated this behavior to force TLS connections unless there is no other alternative.

Anyway – if you’re still running into this against some old sites/servers, it’s worth giving it a try.

Jeff Lindborg
  • 341
  • 2
  • 7
  • 1
    We have a CUCMPowerShell module for using the Cisco Unified Communications AXL api via PowerShell and your answer helped us get this fixed by adding `[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Ssl3`. Thank you! Full code can be seen in the [Invoke-CUCMSOAPAPIFunction](https://github.com/Tervis-Tumbler/CUCMPowerShell/blob/master/CUCMPowerShell.psm1#L181) – Chris Magnuson Sep 01 '16 at 14:51
  • 2
    @Jeff - Check out the linked article. I think it may explain why Ssl3 did not work and suggests two ways to re-enable Ssl3. https://learn.microsoft.com/en-us/dotnet/framework/migration-guide/mitigation-tls-protocols – Scott Sep 05 '17 at 17:34
6

move this line: ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Before this line: HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

Original post: KB4344167 security update breaks TLS Code

user2686690
  • 175
  • 2
  • 3
  • 1
    After trying all of the above to no avail, this was the answer: the ServicePointManager needs to be set before creating the HttpWebRequest. – Henry Rusted Jan 31 '19 at 19:39
5

I'm using .NET version 4.8 and specifying the SSL protocol during the initialization of the HttpClient worked for me to resolve this issue, as shown below.

var client = new HttpClient(new HttpClientHandler { SslProtocols = SslProtocols.Tls12});
vak
  • 51
  • 1
  • 3
  • This is much better answer than setting the "ServicePointManager.SecurityProtocol" since application can have multiple httpClients communicating with different apis etc so you might want/need different setting for each of them. This should be the accepted answer. – Esko Nov 24 '22 at 12:08
2

In my case TLS1_2 was enabled both on client and server but the server was using MD5 while client disabled it. So, test both client and server on http://ssllabs.com or test using openssl/s_client to see what's happening. Also, check the selected cipher using Wireshark.

Imran Qadir Baksh - Baloch
  • 32,612
  • 68
  • 179
  • 322
1

TLS 1.0 and 1.1 are now End of Life. A package on our Amazon web server updated, and we started getting this error.

The answer is above, but you shouldn't use tls or tls11 anymore.

Specifically for ASP.Net, add this to one of your startup methods.

        public Startup()
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;

but I'm sure that something like this will work in many other cases.

Bluebaron
  • 2,289
  • 2
  • 27
  • 37
0

I came across this thread because I also had the error Could not create SSL/TLS secure channel. In my case, I was attempting to access a Siebel configuration REST API from PowerShell using Invoke-RestMethod, and none of the suggestions above helped.

Eventually I stumbled across the cause of my problem: the server I was contacting required client certificate authentication.

To make the calls work, I had to provide the client certificate (including the private key) with the -Certificate parameter:

$Pwd = 'certificatepassword'
$Pfx = New-Object -TypeName 'System.Security.Cryptography.X509Certificates.X509Certificate2'
$Pfx.Import('clientcert.p12', $Pwd, 'Exportable,PersistKeySet')
Invoke-RestMethod -Uri 'https://your.rest.host/api/' -Certificate $Pfx -OtherParam ...

Hopefully my experience might help someone else who has my particular flavour of this problem.

paulf
  • 121
  • 2
  • 2
0

If will work perfect if you specify only TLS in security protocol.

try {
  ServicePointManager.Expect100Continue = true;
  ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

  ServicePointManager.ServerCertificateValidationCallback = delegate {
    return true;
  };

  var webClient = new WebClient();

  var s = webClient.DownloadString("https://google.com");

  Console.WriteLine(s);
} catch (Exception ex) {
  Console.WriteLine(ex);
}
Console.ReadLine();
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • Hello and welcome to StackOverflow! Please provide more details as to what your code does, and why does it answer the question. – Ad5001 Jul 30 '21 at 13:54
  • Actually some frameworks does not use other security protocols so you need to specify TLS. – osama ellahi Aug 02 '21 at 07:12
-2

If you are using a new domain name, and you have done all the above and you are still getting the same error, check to see if you clear the DNS cache on your PC. Clear your DNS for more details.

Windows® 8

To clear your DNS cache if you use Windows 8, perform the following steps:

On your keyboard, press Win+X to open the WinX Menu.

Right-click Command Prompt and select Run as Administrator.

Run the following command:

ipconfig /flushdns

If the command succeeds, the system returns the following message:

Windows IP configuration successfully flushed the DNS Resolver Cache.

Windows® 7

To clear your DNS cache if you use Windows 7, perform the following steps:

Click Start.

Enter cmd in the Start menu search text box.

Right-click Command Prompt and select Run as Administrator.

Run the following command:

ipconfig /flushdns

If the command succeeds, the system returns the following message: Windows IP configuration successfully flushed the DNS Resolver Cache.

JIANG
  • 1,687
  • 2
  • 19
  • 36