“The underlying connection was closed: An unexpected error occurred on a receive” when running WGET, CURL or Invoke-WebRequest on Windows in Powershell

Hi everyone! It has been awhile since I have posted here. Mostly because I have not run into any frustrating issues recently. However this problem really racked my brain until I figured it out.

I was troubleshooting an issue where connecting to a site using any of the PowerShell commands to get web data triggered an error like this:

“The underlying connection was closed: An unexpected error occurred on a receive”

Whereas accessing the site in a web browser worked just fine! Puzzling, right?!

After doing a packet capture and analyzing the traffic, it was apparent that the TLS handshake never began. The TCP handshake was occurring, but nothing after that.

I spent some time going down the rabbit hole of checking the registry’s SCHANNEL settings for SSL & TLS. Sure enough, SSL 1.0 – 3.0 and TLS 1.0 were disabled, per good security hardening measures. RC4 was also disabled, but I wouldn’t expect that cipher to be used for websites’ HTTPS.

To make a long story short, the issue is that older versions of DOTNET framework (i.e. 3.5 and 4.0) do not inherently support the newer versions of TLS like 1.2 and 1.3. You must manually enable them by puttin in regkey settings that tell DOTNET to respect the system-level settings defined in the SCHANNEL hive.

Those settings look like this:

The text you can copy and paste into a .REG file and run on your systems or import to a GPO can be found here: https://pastebin.com/1nCE06Gy

You will want to reboot to ensure the settings get applied.

Note that the newer versions of DOTNET don’t require these registry keys in order to support TLS 1.1 – 1.3, it should work automatically.

As always, test you your changes in a lab because you don’t know what might break whenever you change the smallest item.

More information from Microsoft regarding SSL/TLS can be found here: https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls

Bonus: if you need to list all versions of dotnet installed on a system, then run this in Powershell:

Get-ChildItem ‘HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP’ -Recurse | Get-ItemProperty -Name Version, Release -ErrorAction 0 | where { $_.PSChildName -match ‘^(?!S)\p{L}’} | select PSChildName, Version, Release | FL

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s