388

I'm trying to execute this powershell command

Invoke-WebRequest -Uri https://apod.nasa.gov/apod/

and I get this error. "Invoke-WebRequest : The request was aborted: Could not create SSL/TLS secure channel." https requests appear to work ("https://google.com") but not this one in question. How can I get this to work or use other powershell command to read the page contents?

polina-c
  • 6,245
  • 5
  • 25
  • 36
hewstone
  • 4,425
  • 2
  • 23
  • 24
  • 2
    See also [*Default SecurityProtocol in .NET 4.5*](https://stackoverflow.com/questions/28286086/default-securityprotocol-in-net-4-5). – Franklin Yu Sep 20 '18 at 15:41

7 Answers7

821

try using this one

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri https://apod.nasa.gov/apod/
Chandan Rai
  • 9,879
  • 2
  • 20
  • 28
  • 65
    By default powershell uses TLS 1.0 the site security requires TLS 1.2 – Chandan Rai Jan 12 '17 at 17:05
  • 3
    Awh, How did you determine the TLS version of the site? – hewstone Jan 12 '17 at 17:08
  • 17
    Try [SSLLabs](https://www.ssllabs.com/ssltest/) to determine information: [SSL Report: apod.nasa.gov](https://www.ssllabs.com/ssltest/analyze.html?d=apod.nasa.gov&s=129.164.179.22) shows TLS1.1 and TLS1.2 – Christopher G. Lewis Jan 12 '17 at 18:00
  • @hewstone After time travelling to the future there is a way to sorta answer your the question you implied. IOW How can I just make Invoke-WebRequest work regardless of the destination configuration? – No Refunds No Returns Dec 30 '17 at 03:01
  • 1
    Is there a way to do this that's a little more permanent? This works but seems to reset with every console window. – Brandon Aug 10 '18 at 21:24
  • 3
    @Brandon Change it in `$env:Profile`, or better yet, [edit registry table](https://stackoverflow.com/a/28502562/4451732). – Franklin Yu Sep 23 '18 at 05:15
  • 6
    Sorry Microsoft, but what year is it? [The PCI Council suggested that organizations migrate from TLS 1.0 to TLS 1.1 or higher before June 30, 2018. In October 2018, Apple, Google, Microsoft, and Mozilla jointly announced they would deprecate TLS 1.0 and 1.1 in March 2020.](https://en.wikipedia.org/wiki/Transport_Layer_Security) – KCD May 09 '19 at 02:36
  • @Abr It's not a bug, maybe an oversight, more likely intentional or just late in changing the default. – Chris Dec 05 '19 at 21:27
  • @KCD or maybe it will be addressed in Powershell 7 when people opt in to using it? So a whole bunch of scripts don't suddenly break because of an update being installed. People would be screaming more about that than something they've been living with for who knows how long. Try staying backward compatible forever and shipping new features for 30+ years for complaining too loudly. – No Refunds No Returns Feb 28 '20 at 06:15
  • @No Refunds, normally I'd be sympathetic however `Net.ServicePointManager]::SecurityProtocol` can be set to a set so the only "breaking" change would be that modern TLS no longer return an error? What am i not seeing here? – KCD Feb 29 '20 at 19:07
  • @KCD I posit that modern software has moved to the Chrome Model where there is just one version and it's automagically updated one a regular basis. PS 5 was not designed with this maintenance mode in mind. "What year is it?" Not the year Powershell 5 was designed, built and shipped. Try PS 7 for a modern scripting language created in an era when the threats you fear were fully recognized, included in the design plan and shipped. Stop crying about old software being unable to anticipate unknown threats. Upgrade. Enjoy. – No Refunds No Returns Mar 01 '20 at 15:17
  • FYI, those are 2 different commands. I was trying to run it as one and was getting errors. – Woodchuck Apr 20 '22 at 20:42
  • 1
    Thank you! I ran into this on Windows Server 2016. I did not run into this on Windows Server 2019. – OracleJavaNet Jun 06 '22 at 18:50
225

In a shameless attempt to steal some votes, SecurityProtocol is an Enum with the [Flags] attribute. So you can do this:

[Net.ServicePointManager]::SecurityProtocol = 
  [Net.SecurityProtocolType]::Tls12 -bor `
  [Net.SecurityProtocolType]::Tls11 -bor `
  [Net.SecurityProtocolType]::Tls

Or since this is PowerShell, you can let it parse a string for you:

[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"

Then you don't technically need to know the TLS version.

I copied and pasted this from a script I created after reading this answer because I didn't want to cycle through all the available protocols to find one that worked. Of course, you could do that if you wanted to.

Final note - I have the original (minus SO edits) statement in my PowerShell profile so it's in every session I start now. It's not totally foolproof since there are still some sites that just fail but I surely see the message in question much less frequently.

No Refunds No Returns
  • 8,092
  • 4
  • 32
  • 43
  • 10
    If you need to access a site that uses SSLv3, then you'll want `[Net.ServicePointManager]::SecurityProtocol = "Tls12, Tls11, Tls, Ssl3"`. Remember that SSLv3 and TLSv1.0 have been deprecated due to POODLE, so use at your own risk. – jordanbtucker Mar 01 '18 at 19:43
  • 1
    isnt there a way to use reflection to just allow all Net.SecurityProtocolType types? there has to be – red888 Feb 07 '20 at 21:00
  • 1
    Why do you want to allow known-flawed protocols access by default? Regardless, I believe the imminent (as of this writing) release of PowerShell V7 will address this issue once and for all and this question will slowly fade into its rightful and well-earned oblivion. – No Refunds No Returns Feb 12 '20 at 02:26
  • 2
    In a Dockerfile on Windows use RUN [Net.ServicePointManager]::SecurityProtocol = 'tls12, tls11, tls' ; single apex – Riccardo Bassilichi Apr 08 '21 at 08:48
27

The cause of the error is Powershell by default uses TLS 1.0 to connect to website, but website security requires TLS 1.2. You can change this behavior with running any of the below command to use all protocols. You can also specify single protocol.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls, [Net.SecurityProtocolType]::Tls11, [Net.SecurityProtocolType]::Tls12, [Net.SecurityProtocolType]::Ssl3
[Net.ServicePointManager]::SecurityProtocol = "Tls, Tls11, Tls12, Ssl3"

After running these commands, try running your command:

Invoke-WebRequest -Uri https://apod.nasa.gov/apod/

then it will work.

8

If, like me, none of the above quite works, it might be worth also specifically trying a lower TLS version alone. I had tried both of the following, but didn't seem to solve my problem:

[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls

In the end, it was only when I targetted TLS 1.0 (specifically remove 1.1 and 1.2 in the code) that it worked:

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

The local server (that this was being attempted on) is fine with TLS 1.2, although the remote server (which was previously "confirmed" as fine for TLS 1.2 by a 3rd party) seems not to be.

Hope this helps someone.

Mark-DG1
  • 220
  • 3
  • 8
1

It works for me...

if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type)
    {
    $certCallback = @"
        using System;
        using System.Net;
        using System.Net.Security;
        using System.Security.Cryptography.X509Certificates;
        public class ServerCertificateValidationCallback
        {
            public static void Ignore()
            {
                if(ServicePointManager.ServerCertificateValidationCallback ==null)
                {
                    ServicePointManager.ServerCertificateValidationCallback += 
                        delegate
                        (
                            Object obj, 
                            X509Certificate certificate, 
                            X509Chain chain, 
                            SslPolicyErrors errors
                        )
                        {
                            return true;
                        };
                }
            }
        }
    "@
        Add-Type $certCallback
     }
    [ServerCertificateValidationCallback]::Ignore()

Invoke-WebRequest -Uri https://apod.nasa.gov/apod/
Gowtham Balusamy
  • 728
  • 10
  • 22
  • 4
    This answer effectively disables security checking. While it may eliminate the error it opens your device attack surface in ways that many would consider unacceptable. I would never use this on a device that I own. – No Refunds No Returns Oct 27 '19 at 10:49
  • If you needed this it to make a single request, how would you reset security after the call? – Bevan Feb 08 '23 at 07:17
1

Make sure you switch the SHELL first:

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
RUN Invoke-WebRequest -UseBasicParsing -Uri  'https://github.com/git-for-windows/git/releases/download/v2.25.1.windows.1/Git-2.25.1-64-bit.exe' -OutFile 'outfile.exe'
Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • Are you suggesting this extra step as a way to protect the original PowerShell session from using weaker versions of the protocol? – SamErde Apr 21 '21 at 19:45
  • Thanks. Now it builds on my local machine (Windows 10). "Funny" thing: Docker image was built without this fix on Azure DevOps (`windows-2019` agent) – Saibamen Mar 29 '22 at 09:11
0

I haven't figure out the reason but reinstalling the .pfx certificate(both in current user and local machine) works for me.

Spencer
  • 59
  • 1
  • 11
  • which .pfx did you reinstall? – No Refunds No Returns Oct 27 '19 at 10:50
  • @NoRefundsNoReturns The certificate file which you want to use to send the request. – Spencer Oct 28 '19 at 03:20
  • 1
    I'm still not clear how this is applicable to the question. – No Refunds No Returns Nov 07 '19 at 17:43
  • @NoRefundsNoReturns When I `Invoke-WebRequest` locally, it works at first but will fail later. It seems like sometimes it cannot read the cert any more(I don't know the mechanism behind it. Maybe it's a setting controlled by the company). But reinstalling the cert works in this case. – Spencer Nov 11 '19 at 05:02
  • If you are losing the private key for a certificate that can certainly make the cert unusable but I doubt that's the problem here. If you are losing the key, then you need to make sure you are saving the private key and marking it persistent. Ask a new question if this is what is happening. – No Refunds No Returns Nov 20 '19 at 20:06