6

I am attempting to execute the code below. The errors are self-explanatory but only occur when run remotely. When run locally, all the code works and I can verify that they have the desired effect by pulling content from a web server that requires Tls12 and receiving an error when I have not changed the security protocol.

$tls12 = [Enum]::ToObject([Net.SecurityProtocolType], 3072)
[Net.ServicePointManager]::SecurityProtocol = $tls12

When run on the server, they execute flawlessly. When run remotely via Invoke-Command I receive this error.

Exception setting "SecurityProtocol": "The requested security protocol
is  not supported."
+ CategoryInfo          : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
+ PSComputerName        : servername

Alternatively, this line of code which is fundamentally the same.

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

This also works when run on the server directly but results in this error when run remotely.

Exception setting "SecurityProtocol": "Cannot convert null to type
 "System.Net.SecurityProtocolType" due to invalid enumeration values. Specify one of the following enumeration values and 
try again. The possible enumeration values are "Ssl3, Tls"."
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
+ PSComputerName : servername

The remote server Windows Server 2008 R2 and is running powershell 2.0. The latest Framework version installed is 4.5 release 378389. The machine I am executing from is Windows 10 running powershell 5.0 and Framework 4.6.2 in case it matters.

This is the code I am using to execute it remotely.

$webSession = New-PsSession -ComputerName servername

$cmd = {
    #$tls12 = [Enum]::ToObject([Net.SecurityProtocolType], 3072)
    #[Net.ServicePointManager]::SecurityProtocol = $tls12
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}

Invoke-Command -ScriptBlock $cmd -Session $webSession
remove-pssession  $webSession

If anyone has an idea or suggestion, I would greatly appreciate the help.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Roberto
  • 61
  • 1
  • 3
  • 1
    It successfully runs on the target server directly right, not just on the machine you're trying to send invoke-command from? The error makes it sound like the server only supports `Ssl3` or `Tls` – Sambardo Mar 06 '18 at 22:41
  • The statements do run on the target server. The only time I get the failure is when running them via Invoke-Command. I have verified that the statements work when run on the target server by requesting data from a site that requires Tls12. I can run WebClient.DownloadString and receive an error before executing the commands to enable Tls12. The error indicates that the connection was closed by the server. After executing the statements in my post on the target server, the request succeeds. – Roberto Mar 07 '18 at 15:52
  • Thanks for sharing the trick to get PowerShell 2.0 to use TLS 1.2, at least locally. – Mark Berry Aug 18 '18 at 17:12

1 Answers1

4

[Note: The remainder of this answer SHOULD be true, but ISN'T: Even though the Tls12 value is not defined in an interactive PSv2 session, it can be assigned and takes effect using the OP's workaround, [Net.ServicePointManager]::SecurityProtocol = [Enum]::ToObject([Net.SecurityProtocolType], 3072); by contrast, trying the same thing via PS remoting, using Invoke-Command -ComputerName fails for him. Upgrading PowerShell on the target machine may still be the answer, but this answer offers no explanation of the behavior.]


As Sambardo notes in a comment on the question, the symptom implies that the remote target machine doesn't support the Tls12 value:

PSv2 invariably uses a 2.0 version of the .NET framework, where TLS 1.2 is not supported - irrespective of the presence of newer .NET frameworks on a given machine.

If you run [enum]::GetNames([Net.SecurityProtocolType]) on a machine with PSv2 , you'll see that only the following values are supported:

# PSv2
> [enum]::GetNames([Net.SecurityProtocolType])
Ssl3
Tls

So the answer is to upgrade PowerShell on the remote machine.


As an aside: PowerShell's great flexibility around type conversions allows you to simply use string representations of [enum] values; e.g., the following 2 statements are equivalent:

[Net.ServicePointManager]::SecurityProtocol = 'Tls'

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Any of the statements that I run do work on the target server though. If you have a later version of the framework installed, it should work and it does. https://stackoverflow.com/questions/28286086/default-securityprotocol-in-net-4-5 describes getting it to work in c# but the same thing appears to apply in powershell as long as you are not running a script via Invoke-Command. – Roberto Mar 07 '18 at 21:19
  • @Roberto: Again, what matters is what framework version the PowerShell version you're using is _built on_. Are you saying that running `[Net.SecurityProtocolType] 'Tls12'`, run directly in a *PSv2* window on the server does _not_ fail? Conceivably, you have _multiple_ PS versions installed but it is the PSv2 version that services _remote_ requests. – mklement0 Mar 07 '18 at 21:25
  • 1
    If I run $PSVersionTable.PSVersion in a powershell window on the server, I get major 2, minor 0, build and revision -1. Then if in the same console I run any of the statements I have above, they all succeed. At that point, I can retrieve data from a site I know requires Tls12 in order to work. What you are saying makes perfect sense to me and is what I expect but it is not the behavior that I am seeing when running directly on the target server. – Roberto Mar 07 '18 at 22:41
  • 1
    @Roberto: I can confirm that, curiously, the specific command `[Net.ServicePointManager]::SecurityProtocol = [Enum]::ToObject([Net.SecurityProtocolType], 3072)`, works in an interactive v2 session, despite that enumeration value not existing in v2. By contrast, the _seemingly_ equivalent forms - less surprisingly - do _not_ work: `[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12` and `[Net.ServicePointManager]::SecurityProtocol = 'Tls12'` – mklement0 Mar 08 '18 at 00:06
  • @Roberto: What version numbers does `Get-PSSessionConfiguration` report on the server machine? You could try to set up remoting there again as follows: `Get-PSSessionConfiguration | Unregister-PSSessionConfiguration -force; Enable-PSRemoting -Force` – mklement0 Mar 08 '18 at 17:45