Keywords: PowerShell | HTTPS | Certificate Validation | Invoke-WebRequest | TLS Protocol
Abstract: This article provides an in-depth analysis of connection closure errors encountered when using Invoke-WebRequest and Invoke-RestMethod in PowerShell v3 for HTTPS communications. By examining SSL certificate validation mechanisms and TLS protocol compatibility issues, it presents complete solutions including custom certificate validation policies and protocol configuration methods. With detailed code examples, the article systematically explains the root causes and repair steps, offering practical guidance for developers facing similar HTTPS communication challenges.
Problem Background Analysis
When using Invoke-WebRequest and Invoke-RestMethod for HTTPS communications in PowerShell v3 environment, developers frequently encounter the "The underlying connection was closed: An unexpected error occurred on a send" error. This phenomenon is particularly common when POST requests succeed while GET requests fail, indicating that the issue is unrelated to the request method but rather related to the security mechanisms of HTTPS connections.
SSL Certificate Validation Mechanism
PowerShell's Web cmdlets rely on the .NET Framework's HttpWebRequest class at their core, which by default performs strict SSL certificate validation. Validation may fail when server certificates exhibit the following conditions: expired certificates, incomplete certificate chains, certificate names not matching server domain names, or certificates issued by untrusted certificate authorities.
In the problem description, the user attempted to use [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} to bypass certificate validation, but this approach may not work properly in PowerShell v3 because the ServerCertificateValidationCallback delegate requires more complex implementation.
Core Solution
Based on the best answer solution, we need to implement the ICertificatePolicy interface to customize certificate validation policies. Below is the complete implementation code:
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
$result = Invoke-WebRequest -Uri "https://IpAddress/resource"
This code creates a TrustAllCertsPolicy class through C# type definition, which implements the ICertificatePolicy interface. In the CheckValidationResult method, it always returns true, thereby bypassing all certificate validation checks. This policy is then applied to all subsequent HTTP requests through the [System.Net.ServicePointManager]::CertificatePolicy property.
TLS Protocol Compatibility Enhancement
As a supplementary solution, TLS protocol version compatibility must also be considered. Some servers may only support newer TLS versions, while PowerShell v3 might default to older protocols by default. Below is the complete enhanced solution:
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
This code first defines all supported SSL/TLS protocol versions, including SSL 3.0, TLS 1.0, TLS 1.1, and TLS 1.2. By setting the [System.Net.ServicePointManager]::SecurityProtocol property, it ensures the client can establish secure connections with servers supporting different protocol versions.
Implementation Principle Deep Analysis
The ICertificatePolicy interface is the core mechanism in .NET Framework for customizing certificate validation. When HttpWebRequest establishes an HTTPS connection, it calls the registered certificate policy's CheckValidationResult method to decide whether to accept the server certificate.
In the standard certificate validation process, the system checks certificate validity, certificate authority trust chains, certificate usage, and multiple other aspects. By returning true, we essentially create a "trust all certificates" policy, which is acceptable in development and testing environments but should be used cautiously in production environments.
Regarding TLS protocol configuration, PowerShell v3 runs on .NET Framework 4.0 or 4.5, which may only enable older protocol versions by default. By explicitly setting SecurityProtocol, we ensure the client can communicate normally with servers using modern TLS versions.
Application Scenarios and Considerations
This solution is particularly suitable for the following scenarios: development and testing environments, self-signed certificates in internal networks, or integration with infrastructure using non-standard certificates. However, in production environments, it is recommended to use valid, trusted certificates rather than completely bypassing certificate validation.
It is important to note that trusting all certificates poses security risks and may make systems vulnerable to man-in-the-middle attacks. When this solution must be used, it should be limited to necessary scopes, and migration to solutions using valid certificates should be pursued as soon as possible.
Comparison with Other Tools
The reference article mentions that the CURL tool can successfully connect while PowerShell fails, highlighting differences in HTTPS handling among different tools. CURL offers more flexible certificate validation options and protocol negotiation mechanisms, while PowerShell's Web cmdlets provide tighter .NET integration but may be more stringent in certain security configurations.
Through the solutions provided in this article, developers can maintain PowerShell's convenience while overcoming common obstacles in HTTPS connections, achieving seamless integration with various REST APIs.