Powershell:Invoke-WebRequestに失敗する場合の対処方法(TLS1.2有効化)
こんにちは
AWS WorkspaceからSlackに通知したいことがあると思います。
WindowsからWebhookを叩く際に、PowershellのInvoke-WebRequestを実行すると思います。その際に以下のようなエラーが出ると場合の対処方法について解説します。
Invoke-WebRequest : 要求は中止されました: SSL/TLS のセキュリティで保護されているチャネルを作成できませんでした
Invoke-WebRequest : 接続が切断されました: 送信時に、予期しないエラーが発生しました
対処方法
以下のコマンドを実行して、TLS1.2を有効化することで回避する可能性があります。
> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
前提条件
クライアント
- Windows OS全般
サイト(Slack)
2021/08/21時点では、Slack は、Transport Layer Security(TLS)のバージョン 1.2 をサポートしています。
そのため、TSL1.2でリクエストをする必要性があります。
対処方法
クライアントのTSLバージョンを確認する
クライアントで有効化しているTSLのバージョンを確認するには以下のコマンドを実行します
> [Net.ServicePointManager]::SecurityProtocol
Ssl3,Tsl
このケースでは、クライアントがTSL1.0、サイトがTSL1.2をサポートなので、リクエストを処理できません
利用可能な接続方式を確認する
以下のコマンドで、実行環境で利用可能な接続方式を確認することができます
> [enum]::GetNames([Net.SecurityProtocolType])
SystemDefault
Ssl3
Tls
Tls11
Tls12
Tls13
TLS1.2が利用可能なのを確認できました
一時的にTSL1.2を有効化する
以下のコマンドで、一時的にTSL1.2を有効化することができます
> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
確認し、TSL1.2が有効化することを確認します
> [Net.ServicePointManager]::SecurityProtocol
Tls12
これで、クライアント、サイトともにTSL1.2でしゃべるので、当初の Invoke-WebRequest
コマンドを実行してください
Tips
今回の記載から脱線してしまうTpisをまとめました
1. TSLバージョンを複数指定したい
以下のコマンドで、複数の接続方式を有効化することができます
(今回の例では、TLS1.3とTLS1.2を有効化しています)
> [System.Net.ServicePointManager]::SecurityProtocol = @([System.Net.SecurityProtocolType]::Tls13,[System.Net.SecurityProtocolType]::Tls12)
Tls13,Tls12
2. PowerShellを起動したら、自動的にTLS1.2を有効化したい
今回記載した方法は、PowerShellを起動する度に、TLS1.2を有効化するコマンドを入力する必要があるため、少々面倒だと思います
そこで、PowerShellを起動したら、自動的にTLS1.2を有効化するように設定します
(bashでいう.bash_profile のようなものを設定します。レジストリからも設定できるようですが、あまりいじりたくないので)
下記コマンドで PowerShell のプロファイルの場所を確認します
> $profile
C:\Users\xxxxxx\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
コマンドの実行結果より、C:\Users\xxxxxx\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
をテキストエディタで開きます
下記を追記してファイルを保存します
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
新たにPowerShellを起動し、以下の実行結果が Tls12
と表示されれば設定完了です
> [Net.ServicePointManager]::SecurityProtocol
Tls12
これで、毎回TLSバージョン指定する必要がなくなりました
補足
他サイトの場合で同様の事象が発生し、TSLバージョンでも再発する場合、以下の対処で回避する可能性があります
1. サイトがBASIC認証をかけている
- 以下のようにID、パスワードをいれてあげます。
$USER = "username"
$PASS = "password"
$secpasswd = ConvertTo-SecureString $PASS -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($USER, $secpasswd)
2. サイト側が自己証明書をつかっている
- いわゆる、オレオレ証明書を利用しているバターンとなります
- 以下のスプリクトを追加してあげるとうまくいきました
- httpsの場合、サーバー証明書をチェックしているようで、
CertificatePolicy
のCheckValidationResult
メソッドを無条件でTrueを返しているようです
- httpsの場合、サーバー証明書をチェックしているようで、
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
参考文献
Discussion