What should have been just another quick PowerShell script performing a WebRequest to get some data, turned into a debugging session when both the Invoke-RestMethod and Invoke-WebRequest PowerShell commands were returning; The underlying connection was closed: An unexpected error occurred on a send.
Invoke-RestMethod
Here is the PowerShell Invoke-RestMethod response that returns: The underlying connection was closed: An unexpected error occurred on a send.
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send. At line:1 char:15 + ... postdata2 = Invoke-RestMethod -Uri $post.URL -Method Get -UserAgent $ ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Invoke-WebRequest
Here is the PowerShell Invoke-WebRequest response that returns: The underlying connection was closed: An unexpected error occurred on a send.
Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send. At line:3 char:21 + ... $postdata = Invoke-WebRequest -Uri $post.URL -Method Get -UserAgent $ ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Due to PowerShell defaults, it’s not unusual to have issues with TLS. The ambiguous nature of this error did however make me jump to the conclusion that I probably just needed to enforce TLS 1.2. This can be done using this PowerShell one-liner:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
However, in this situation that wasn’t the fix. Thinking it was still TLS related I checked out the SSL Certificate for the URI I was making my webrequests against. Looking at the certificate showed it was valid.
Solution
After a lot of searching I was able to work around the problem using scenarios from (here and here), however they weren’t ideal.
The resolution and solution I’m using to resolve the problem is to allow TLS, TLS 1.1 and TLS 1.2.
Insert the following line before invoking your PowerShell WebRequest using either Invoke-RestMethod or Invoke-WebRequest.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
Summary
Hopefully this helps others experiencing this error, and allows me to quickly find it again next time I encounter this issue.
Also checkout my PowerShell Snippets Vol 1 and Vol 2 for other simple resolutions to ambiguous errors and tasks.
The underlying connection was closed: an unexpected error occurred on a send.
To resolve the PowerShell “underlying connection was closed” error, in your PowerShell script enable TLS:
Add the following line before your Invoke-RestMethod or Invoke-WebRequest call;
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor
[Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
Applies To : PowerShell
Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send
December 29, 2019 05:25PM
I was setting up a local on premises PSRepository server for collaboration purpose between my team also future planning is to limit users downloading modules from only from in-house PowerShell repositories. Local repository was setup but while publishing module on the repository I was getting below error.
Publish-Module -Path C:On -Repository OnPremRepo -Force Microsoft.PowerShell.UtilityInvoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send. At C:Program FilesWindowsPowerShellModulesPowerShellGet1.0.0.1PSModule.psm1:7448 char:21 + ... $null = Microsoft.PowerShell.UtilityInvoke-WebRequest -Uri $scri ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand Publish-Module : NuGet.exe is required to interact with NuGet-based repositories. Please ensure that NuGet.exe is available under one of the paths specified in PATH environment variable value. At line:1 char:1 + Publish-Module -Path C:HW -Repository OnPremRepo -Force + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Publish-Module], InvalidOperationException + FullyQualifiedErrorId : CouldNotInstallNuGetExe,Publish-Module
Related Articles
Get-PSRepository WARNING Unable to find module repositories
Creating an internal PowerShell module repository
After reading the complete error next statement caught into my eyes «Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send». This error statement is because of, by default PowerShell web request calls happens over TLS 1.0 version (TLS 1.0 is vulnerable and security best practice suggests it should be disabled), So you need to configure powershell to use TLS 1.2 version instead of the default TLS 1.0.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Once I switched to TLS 1.2 version and tried publishing module and it was successful.
Publish-Module -Path C:On -Repository OnPremRepo NuGet.exe is Required to continue PowerShellGet requires NuGet.exe to publish an item to the NuGet-based repositories. NuGet.exe must be available in 'C:ProgramDataMicrosoftWindowsPowershellPowerShellGet' or 'C:Usersvcloud.VCLOUD-LABAppDataLocalMicrosoftWindowsPowerShellPowerShellGet', or under one of the specified in PATH environment variable value. NuGet.exe can be downloaded from http://nuget.org/nuget.exe, do you want PowerShellGet to install NuGet.exe now? [Y] Yes [N] No [S] Suspend [?] Help (default is "Y"): Y
Useful Articles
GUI — SETUP AND CONFIGURE POWERSHELL WEB ACCESS SERVER (GATEWAY)
USE POWERSHELL ON MOBILE — SETUP AND CONFIGURE POWERSHELL WEB ACCESS (PSWA)
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Powershell Trick : Execute or run any file as a script file
Set Powershell execution policy with Group Policy
Powershell execution policy setting is overridden by a policy defined at a more specific scope
Go Back
This seems to be more of a protocol issue than a cert issue. On my Windows Server 2016 box [System.Net.ServicePointManager]::SecurityProtocol
returns Ssl3, Tls
.
According to SSL Server Test, update.code.visualstudio.com supports TLS 1.2 only, which would explain the connection refused.
This can be confirmed in PowerShell by trying to connect to https://update.code.visualstudio.com/ before and after turning TLS 1.2 on:
TLS 1.2 off
> Invoke-WebRequest https://update.code.visualstudio.com/
Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.
At line:1 char:1
+ Invoke-WebRequest https://update.code.visualstudio.com/
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
TLS 1.2 on
> [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
> Invoke-WebRequest https://update.code.visualstudio.com/
StatusCode : 200
StatusDescription : OK
Content : Hello from VS Code! 👋
RawContent : HTTP/1.1 200 OK
request-context: appId=cid-v1:8109e553-6232-492a-afca-b78cea9b431c
Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
X-Source-Commit: 5b1e6aaf6afec2feec21...
Forms : {}
Headers : {[request-context, appId=cid-v1:8109e553-6232-492a-afca-b78cea9b431c], [Strict-Transport-Security,
max-age=31536000], [X-Content-Type-Options, nosniff], [X-Source-Commit,
5b1e6aaf6afec2feec218a378676e943da8f7885]...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : System.__ComObject
RawContentLength : 24
Опишу возможные варианты поиска и решения проблем возникновения ошибок
System.Net.Http.HttpRequestException: The SSL connection could not be established
The underlying connection was closed: An unexpected error occurred on a send.
Проявляться может при вызове Invoke-WebRequest с операционной системы Windows:
+ Invoke-WebRequest -URI https://nodejs.org/dist/v16.14.2/node-v16.14.2 ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc eption + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
В Event viewer при этом могут возникать ошибки вида:
EventID 36871 A fatal error occurred while creating an SSL client credential. The internal error state is 10013. Schannel
EventID 36874 An SSL 2.0 connection request was received from a remote client application, but none of the cipher suites supported by the client application are supported by the server. The SSL connection request has failed.
1. Просмотр какие протоколы используются на целевой странице
Через браузер (не системный) или другую систему смотрим в инструментах разработчика что используется, например:
Protocol TLS 1.3 Key exchange group X25519 Cipher AES_128_GCM
2. Настройки SSL и TLS
Согласно документации Microsoft настраиваем параметры TLS в реестре.
Пример включения TLS 1.2. Client
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionInternet SettingsWinHttp DefaultSecureProtocols = (DWORD): 0xAA0 HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionInternet SettingsWinHttp DefaultSecureProtocols = (DWORD): 0xAA0
настройки производить в параметрах реестра:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.2Client] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.1Client] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Client] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 2.0Client] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 3.0Client] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.2Server] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.1Server] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 2.0Server] HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsSSL 3.0Server]
Включить базово использование протоколов можно через системное окно настроек обозревателя, например для SSL 3.0
Internet Options > Advanced > Settings > Security > Use SSL 3.0.
Дополнительно можем задать подключение после активаци в реестре из коммандной строки и попробовать
[Net.ServicePointManager]::SecurityProtocol = "tls13, tls12, tls11, tls,SSL3"
3. Настройки алгоритмов шифрования
В реестре в ветке
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNEL
проверяем не выключены ли протоколы шифрования
4. Обновляем .netFramework до версии поддерживающей протоколы
В частности TLS 1.3 используется в .netFramework 4.8. В ОС до windows server 2016 может отсутствовать поддержка (зависит от обновлений) — в этом случае используем ОС с поддержкой требуемых протоколов.
TLS 1.
Посмотреть какие .NetFramework используются в системе можно из PowerShell
Get-ChildItem 'HKLM:SOFTWAREMicrosoftNET Framework SetupNDP' -Recurse | Get-ItemProperty -Name version -EA 0 | Where { $_.PSChildName -Match '^(?!S)p{L}'} | Select PSChildName, version