Invoke-WebRequest 对于 HTTPS 总是失败。根据验证程序,远程证书无效
Invoke-WebRequest Always Fails For HTTPS. The remote certificate is invalid according to the validation procedure
我正在尝试在 pwsh
(在 Linux)中使用 Invoke-WebRequest,但总是失败。这是一个例子:
Invoke-WebRequest https://www.google.com
site/URL 没关系,如果它使用 HTTPS 我会得到错误。在 Windows 机器上运行完全相同的脚本没有问题。
$PSVersionTable
> Name Value
> ---- -----
> PSVersion 7.0.0
> PSEdition Core
> GitCommitId 7.0.0
> OS Linux 3.10.0-514.21.1.el7.x86_64 #1 SMP Thu May 25 17:04:51 UTC 2017
> Platform Unix
> PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
> PSRemotingProtocolVersion 2.3
> SerializationVersion 1.1.0.1
> WSManStackVersion 3.0
dotnet --version
3.1.403
openssl版本
OpenSSL 1.0.1e-fips 11 Feb 2013
我知道可以在 Invoke-WebRequest 方法上禁用 SSL 验证,但我真的宁愿避免它,而且,我在执行 dotnet restore
[=30 之类的操作时也遇到了同样的问题=]
如果我使用 curl https://www.google.com
,它似乎工作正常。我的理解是 pwsh 使用 dotnet 来实际发出这个 webrequest,而 dotnet 使用 openssl 作为 https...这可能都是错误的,但我一直在尝试使用 openssl 进行调试。
当我执行 openssl s_client -connect www.google.com:443
时,似乎表明一切正常。我可以看到证书链:
> Certificate chain
> 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
> i:/C=US/O=Google Trust Services/CN=GTS CA 1O1
> 1 s:/C=US/O=Google Trust Services/CN=GTS CA 1O1
> i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
和0的return代码(ok)
Start Time: 1612285043
Timeout : 300 (sec)
Verify return code: 0 (ok)
如果我在 .ps1
脚本中捕获到异常,我可以看到更多信息:
The remote certificate is invalid according to the validation procedure.
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(HttpClient client, HttpRequestMessage request, Boolean keepAuthorization)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
但我仍然不知道下一步该去哪里。
最后 - 虽然我无法确定发生了什么变化,但我知道这个曾经在这台机器上工作。我很想将所有内容都升级到最新版本,但是当它与我现在拥有的版本一起使用时,很难证明这种更改是合理的。
谁能帮我指明正确的方向?
编辑
附加信息 - 当我 运行 curl -verbose https://www.google.com 我看到正在使用哪个证书:
* Connected to www.google.com (74.125.195.105) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
我没有看到 openssl 的 s_client 的等效项,但是 运行ning strace -e open openssl s_client -connect www.google.com:443 | & grep open 显示:
open("/etc/pki/tls/openssl.cnf", O_RDONLY) = 3
open("/etc/pki/tls/cert.pem", O_RDONLY) = 3
但我没能看到 pwsh
试图访问我安装的任何根 ca。当我在线搜索时,我只看到很多人说 Linux 上的 dotnet 核心使用 OpenSSL,我应该查看 openssl.cnf
文件 - 但是当我从命令行使用 openssl 时,似乎上班?!?
再次 - 任何帮助将不胜感激。似乎 pwsh 没有使用我拥有的证书?
由于您要求的是指导而不是解决方案:几乎可以肯定的是,powershell 不知道在哪里可以找到要信任的证书颁发机构的信任库。弄清楚如何告诉它信任库在哪里,或者弄清楚如何用特定证书告诉 invoke-webrequest 是我要开始的地方。
我正在尝试在 pwsh
(在 Linux)中使用 Invoke-WebRequest,但总是失败。这是一个例子:
Invoke-WebRequest https://www.google.com
site/URL 没关系,如果它使用 HTTPS 我会得到错误。在 Windows 机器上运行完全相同的脚本没有问题。
$PSVersionTable
> Name Value
> ---- -----
> PSVersion 7.0.0
> PSEdition Core
> GitCommitId 7.0.0
> OS Linux 3.10.0-514.21.1.el7.x86_64 #1 SMP Thu May 25 17:04:51 UTC 2017
> Platform Unix
> PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
> PSRemotingProtocolVersion 2.3
> SerializationVersion 1.1.0.1
> WSManStackVersion 3.0
dotnet --version
3.1.403
openssl版本
OpenSSL 1.0.1e-fips 11 Feb 2013
我知道可以在 Invoke-WebRequest 方法上禁用 SSL 验证,但我真的宁愿避免它,而且,我在执行 dotnet restore
[=30 之类的操作时也遇到了同样的问题=]
如果我使用 curl https://www.google.com
,它似乎工作正常。我的理解是 pwsh 使用 dotnet 来实际发出这个 webrequest,而 dotnet 使用 openssl 作为 https...这可能都是错误的,但我一直在尝试使用 openssl 进行调试。
当我执行 openssl s_client -connect www.google.com:443
时,似乎表明一切正常。我可以看到证书链:
> Certificate chain
> 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
> i:/C=US/O=Google Trust Services/CN=GTS CA 1O1
> 1 s:/C=US/O=Google Trust Services/CN=GTS CA 1O1
> i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
和0的return代码(ok)
Start Time: 1612285043
Timeout : 300 (sec)
Verify return code: 0 (ok)
如果我在 .ps1
脚本中捕获到异常,我可以看到更多信息:
The remote certificate is invalid according to the validation procedure.
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(HttpClient client, HttpRequestMessage request, Boolean keepAuthorization)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
但我仍然不知道下一步该去哪里。
最后 - 虽然我无法确定发生了什么变化,但我知道这个曾经在这台机器上工作。我很想将所有内容都升级到最新版本,但是当它与我现在拥有的版本一起使用时,很难证明这种更改是合理的。
谁能帮我指明正确的方向?
编辑
附加信息 - 当我 运行 curl -verbose https://www.google.com 我看到正在使用哪个证书:
* Connected to www.google.com (74.125.195.105) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
我没有看到 openssl 的 s_client 的等效项,但是 运行ning strace -e open openssl s_client -connect www.google.com:443 | & grep open 显示:
open("/etc/pki/tls/openssl.cnf", O_RDONLY) = 3
open("/etc/pki/tls/cert.pem", O_RDONLY) = 3
但我没能看到 pwsh
试图访问我安装的任何根 ca。当我在线搜索时,我只看到很多人说 Linux 上的 dotnet 核心使用 OpenSSL,我应该查看 openssl.cnf
文件 - 但是当我从命令行使用 openssl 时,似乎上班?!?
再次 - 任何帮助将不胜感激。似乎 pwsh 没有使用我拥有的证书?
由于您要求的是指导而不是解决方案:几乎可以肯定的是,powershell 不知道在哪里可以找到要信任的证书颁发机构的信任库。弄清楚如何告诉它信任库在哪里,或者弄清楚如何用特定证书告诉 invoke-webrequest 是我要开始的地方。