ChatGPT解决这个技术问题 Extra ChatGPT

Powershell Invoke-WebRequest Fails with SSL/TLS Secure Channel

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?


C
Chandan Rai

try using this one

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri https://apod.nasa.gov/apod/

By default powershell uses TLS 1.0 the site security requires TLS 1.2
Awh, How did you determine the TLS version of the site?
Try SSLLabs to determine information: SSL Report: apod.nasa.gov shows TLS1.1 and TLS1.2
@Brandon Change it in $env:Profile, or better yet, edit registry table.
N
No Refunds No Returns

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.


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.
isnt there a way to use reflection to just allow all Net.SecurityProtocolType types? there has to be
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.
In a Dockerfile on Windows use RUN [Net.ServicePointManager]::SecurityProtocol = 'tls12, tls11, tls' ; single apex
S
Sidrah Madiha Siddiqui

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.


M
Mark-DG1

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.


G
Gowtham Balusamy

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/

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.
p
pixelbits

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'

Are you suggesting this extra step as a way to protect the original PowerShell session from using weaker versions of the protocol?
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)
S
Spencer

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


which .pfx did you reinstall?
@NoRefundsNoReturns The certificate file which you want to use to send the request.
I'm still not clear how this is applicable to the question.
@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.
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.