33

When I try to use Invoke-WebRequest I'm getting some weird error:

Invoke-WebRequest -Uri "https://idp.safenames.com/"

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

I'm not sure what's causing it, as the website itself seems fine.

Even with all the "ignore ssl errors" functions around stackoverflow, it's still not working, making me wonder if it's related to SSL at all.

3

4 Answers 4

68

As BaconBits notes, .NET version > 4.5 uses SSLv3 and TLS 1.0 by default.

You can change this behavior by setting the SecurityProtocol policy with the ServicePointManager class:

PS C:\> $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
PS C:\> [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
PS C:\> (Invoke-WebRequest -Uri "https://idp.safenames.com/").StatusCode
200

This will apply to all requests in the AppDomain (so it only applies to the current instance of the host application).


There's a module on GitHub and in PSGallery that can manage these settings now:

Install-Module BetterTls -Scope CurrentUser
Import-Module BetterTls
Enable-Tls -Tls11 -Tls12
Sign up to request clarification or add additional context in comments.

6 Comments

What am I doing wrong? I seriously can't tell... imgur.com/FgHqF1o
Powershell 4.0 or 4 0 -1 -1 when using the psversiontable.psversion query
Behavior repro on 2 diff windows boxes, win8.1 & 10
@Cheeso - the best thing you can do (or more accurately, the only thing) is to enable SChannel debugging as per support.microsoft.com/en-us/help/260729/… ... annoyingly, this usually needs a reboot to actually take effect. SChannel is the windows subsystem dedicated to SSL/TLS connection and session management, so anything using the Windows APIs for SSL/TLS connections will go through it. Log events go into the windows event viewer logs. Should work for clients as well as servers.
Setting accepted TLS versions on application code goes against best practices recommended by Microsoft. TLS 1.0 and 1.1 are deprecated. An application that uses will fail again if TLS 1.2 is deprecated as well.
|
16

This can be permanently changed as well

# set strong cryptography on 32 bit .Net Framework (version 4 and above)
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
# set strong cryptography on 64 bit .Net Framework (version 4 and above)
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 

1 Comment

12

Based on this scan, it doesn't look like that URI supports anything lower than TLS 1.1.

What version of Windows are you on? If you're on PowerShell v4.0 or lower, you're not going to be able to negotiate a TLS 1.1 or 1.2 connection because the .Net Framework doesn't support TLS 1.1 or 1.2 until .Net Framework 4.5. PowerShell v4.0 is .Net 4.0. That means the underlying System.Net.WebRequest classes can't negotiate a connection. I believe PowerShell v5.0 is .Net 4.5 or .Net 4.6, but I don't have a Win 10 client to check the $PSVersionTable right now.

You may be able to get it to work by coding the calls to WebRequest manually and specifying the protocol as [System.Net.SecurityProtocolType]::Tls12 or [System.Net.SecurityProtocolType]::Tls11, but I'm not sure if that's possible. That's supposed to work if .Net 4.5 is installed from what I'm seeing, but, again, I've never tried it.

For reference, I get the exact same results as you on Windows 7 x64/Powershell v4.0 and I've got .Net 4.5 installed, but I've never tried manually coding the WebRequest. I also get an error if I use wget for Windows 1.11.4 from here (OpenSSL 0.9.8b, well before TLS 1.1 and 1.2), but it works just fine if I use wget for Windows 1.17.1 from here (current, more or less).

2 Comments

Helpful, but.... The original question said I'm not sure what's causing it Teach a person to fish.... How do we know that it's a TLS problem? I had this situation and could not, for the life of me, get anything out of the WebException that said "error during TLS negotiation". Worse, the problem appeared only during automated tests, not manual tests. How, on the client side, could I get a message that says "the client tried to negotiate with TLS 1.0 and the server rejected it." Or SOME kind of pseudo-English explanation for the error, beyond "An unexpected error occurred on a send."
@Cheeso You're often not going to get a helpful error here at all because the server doesn't return an error to the client. It just terminates the connection. All the client knows is that the connection ended or was refused. You'd need to watch the communication with Wireshark, which isn't fun with TLS.
4

One line:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

3 Comments

This answer repeats (some) information available in much earlier answers, but does not include any explanation. Nor is the code actually much simpler.
This should have been the accepted answer
The one-liner that corresponds to the accepted answer is: [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType] 'Ssl3, Tls, Tls11, Tls12' (at least in v5.1 you don't even need the [System.Net.SecurityProtocolType] cast); recent .NET versions additionally support Tls13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.