WebサイトやWebアプリのセキュリティの要である「SSL/TLS」は、SSL 3.0以前のレガシーなプロトコルの脆弱(ぜいじゃく)性が問題視され、より新しいプロトコルに移行することが求められてきました。SSLの後継であるTLS 1.0/1.1も脆弱性があることが明らかになり、最近ではTLS 1.2以降を要求するWebサイトやサービスも増えてきています(例:2019年7月下旬のTwitterサービスなど)。今回は、TLS 1.2以降への移行の影響で失敗するようになった「Invoke-WebRequest」コマンドレットの回避策について。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
筆者は「Windows Sysinternals」のユーティリティーの更新版を素早く手に入れられるように、自作のWindows PowerShellスクリプト「updatesysinternalssuite.ps1」を作成し、利用しています。作成したスクリプトは、「TechNetスクリプトセンター」で公開しています。
このスクリプトはWindows PowerShell 5.0以降で動作します。「Invoke-WebRequest」コマンドレットは、Windows PowerShell 3.0以降で利用できますが、zipファイルの展開に利用している「Expand-Archive」コマンドレットはWindows PowerShell 5.0以降から利用できるようになったものだからです。
現在、公開されているスクリプトは、本稿で説明する問題への対応を含む修正版になります。修正前のスクリプトは、2018年10月前半までは問題なく機能していました。それが2018年10月後半、突然、「Invoke-WebRequest:接続が切断されました:受信時に予期しないエラーが発生しました。」というエラーが表示されるようになりました(画面1)。
調査してみると、Invoke-WebRequestコマンドレットによるファイルのダウンロード元「https://live.sysinternals.com/」サイトが、TLS 1.2を要求するようになったことが分かりました。しばらく前から常時SSLサイトになったため、HTTP接続はできません。TLS 1.0以前やTLS 1.3(Windows 10 バージョン1903から追加)ではHTTPS接続できず、TLS 1.2のHTTPS接続のみを受け付けるようにサイト側が変更されたのです。
ちなみに、当時使用していたWindowsのバージョンはWindows 10 バージョン1803でした。そして、Windows 10 バージョン1809以降のInvoke-WebRequestは、エラーなしで問題なく動作します。
Windowsは、「Windows 7」と「Windows Server 2008 R2」でTLS 1.1/1.2に標準対応しました。ただし、TLS 1.1/1.2を利用するには、追加の設定が必要になる場合があります。必要な設定については以下の公式ブログのアーカイブにまとめられていますが、Windowsのバージョン、.NET Frameworkのバージョン、使用するアプリの組み合わせによって、TLS 1.2に対応させる方法はさまざまです。
Windows PowerShellのInvoke-WebRequest(Windows PowerShell 3.0以降で利用可能)は、.NET Framework上で動作するアプリケーションといえます。
今回は、Windows 10 バージョン1803以前のInvoke-WebRequest(およびInvoke-RestMethod)の、使用されるセキュリティプロトコルによる接続エラーの解消方法に焦点を当てて、サポート対象のWindowsの全バージョンについてまとめました。なお、対象のWindowsでサポートされる.NET Framework 4.5.2以降がインストールされ、最新の更新プログラムが適用済みであることを前提とします。
Invoke-WebRequestは、.NET Frameworkの「Net.ServicePointManager」の「SecurityProtocol」プロパティに設定されているプロトコルバージョンを使用して、HTTPS接続を行おうとします。Windows PowerShellで以下のコマンドラインを実行すると、システムのSecurityProtocolプロパティの設定を参照することができます(「PS:¥>」はプロンプトであり入力する必要なし)。また、「[enum]::GetNames([Net.SecurityProtocolType])」を実行すると、システムで利用可能なプロトコルバージョンのリストを確認できます。
PS:¥> [Net.ServicePointManager]::SecurityProtocol PS:¥> [enum]::GetNames([Net.SecurityProtocolType])
Windows 10 バージョン1803以前の場合、1行目のコマンドラインはシステムの既定値を変更していない限り、「Ssl3, Tls」を返します。つまり、Windows 10 バージョン1803以前のInvoke-WebRequestは、SSL 3.0またはTLS 1.0を使用してHTTPS接続しようとします。そのため、TLS 1.1以降のサイトに接続しようとすると、エラーで失敗します。
Windows 10 バージョン1809以降では、次の値を返します。Windows 10 バージョン1809以降のInvoke-WebRequestでTLS 1.2のみのサイトへの接続がエラーにならないのは、既定の設定がより安全なプロトコルを使用するように変更されたからです。
Windows Sysinternalsのサイトから接続エラーを回避して「Process Explorer」(Procexp.exe)をダウンロードするには、以下のようにTLS 1.2の使用を明示的に指定してから実行します(画面2)。
PS:¥> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 PS:¥> Invoke-WebRequest -uri https://live.sysinternals.com/procexp.exe -outfile .¥procexp.exe
この方法は公式ブログのまとめには直接書いていませんが、アプリ側で“ServicePointManager.SecurityProtocol プロパティに明示的に指定”する方法になります。現在(修正版)の「updatesysinternalssuite.ps1」には、1行目にこのコマンドラインを追記してあります。
TLS 1.0、TLS 1.1またはTLS 1.2から、より最適なプロトコルを利用させたい場合は、以下のように記述します。
PS:¥> [Net.ServicePointManager]::SecurityProtocol = @([Net.SecurityProtocolType]::Tls,[Net.SecurityProtocolType]::Tls11,[Net.SecurityProtocolType]::Tls12)
この方法は、TLS 1.1/1.2に標準で対応しているWindows 7とWindows Server 2008 R2以降の全てに共通で使える方法です。後述しますが、Windows Server 2008についても、TLS 1.1/1.2をサポートする更新プログラムがインストール済みであれば使える方法です。
Windows 10 バージョン1803以前で接続エラーを回避するもう一つの方法は、システムの既定のSSL 3.0/TLS 1.0(Ssl3, Tls)から、Windows 10 バージョン1809と同じTLS 1.0以降(Tls, Tls 1.1, Tls 1.2)に変更する方法です。
それには、次の場所にあるレジストリキーに、DWORD(REG_DWORD)型の値を「SchUseStrongCrypto」という名前で作成し、値のデータを「1」に設定します。なお、32bit(x86)OSの場合、「HKEY_LOCAL_MACHINE¥SOFTWARE¥Wow6432Node」下のレジストリ値の作成は不要です。
HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥.NETFramework¥v4.0.30319
HKEY_LOCAL_MACHINE¥SOFTWARE¥Wow6432Node¥Microsoft¥.NETFramework¥v4.0.30319
コマンドプロンプトまたはWindows PowerShellを管理者として開き、次のコマンドラインを実行します(HKEY_LOCAL_MACHINEは、HKLMの短縮形で記述可能です)。
PS:¥> REG ADD "HKLM¥SOFTWARE¥Microsoft¥.NETFramework¥v4.0.30319" /v "SchUseStrongCrypto" /t REG_DWORD /d 1 /f PS:¥> REG ADD "HKLM¥SOFTWARE¥Wow6432Node¥Microsoft¥.NETFramework¥v4.0.30319" /v "SchUseStrongCrypto" /t REG_DWORD /d 1 /f
レジストリ値の作成後、Windows PowerShellの新しいウィンドウを開くと、システムの既定値が変更されたことを確認できるでしょう(画面3)。この設定は、公式ブログの「6. .NET Framework 4.5.2でTLS 1.1および1.2を既定値にするための方法」の設定と同じものです。
繰り返しますが、Windows 10 バージョン1809以降、Windows Server 2019、Windows Server, version 1809以降では、TLS 1.0/1.1/1.2(バージョン1809)およびTLS 1.3(バージョン1903以降)を標準で利用可能なので、追加の設定は必要ありません。
前述したように、OSとしてTLS 1.1/1.2に標準対応したのは、Windows 7とWindows Server 2008 R2からです。Windows Server 2008は、標準でSSL 3.0以前およびTLS 1.0にのみ対応していました。TLS 1.1/1.2のサポートは、Windows Server 2008 SP2向けの更新プログラムによって提供されました。Windows Updateで最新の状態に更新されていれば、TLS 1.1/1.2に対応済みです。
Windows Server 2008でInvoke-WebRequestを利用するには、Windows PowerShell 3.0(WMF 3.0に含まれる)がインストールされている必要もあります。その上でコマンドプロンプトまたはWindows PowerShellを管理者として開き、次の6行のコマンドラインを実行することで、システムの既定値を変更できます(画面4)。
PS:¥> REG ADD "HKLM¥SYSTEM¥CurrentControlSet¥Control¥SecurityProviders¥SCHANNEL¥Protocols¥TLS 1.1¥Client" /v "DisabledByDefault" /t REG_DWORD /d 0 /f PS:¥> REG ADD "HKLM¥SYSTEM¥CurrentControlSet¥Control¥SecurityProviders¥SCHANNEL¥Protocols¥TLS 1.2¥Client" /v "DisabledByDefault" /t REG_DWORD /d 0 /f PS:¥> REG ADD "HKLM¥SOFTWARE¥Microsoft¥.NETFramework¥v4.0.30319" /v "SchUseStrongCrypto" /t REG_DWORD /d 1 /f PS:¥> REG ADD "HKLM¥SOFTWARE¥Wow6432Node¥Microsoft¥.NETFramework¥v4.0.30319" /v "SchUseStrongCrypto" /t REG_DWORD /d 1 /f
32bit(x86)OSの場合、「HKLM¥SOFTWARE¥Wow6432Node」下のレジストリの設定は不要です。また、今回は念のために設定しましたが、Invoke-WebRequestのために「HKLM¥SYSTEM¥CurrentControlSet¥Control¥SecurityProviders¥SCHANNEL¥Protocols」下のレジストリキーの作成(最初の2行)は必須ではないかもしれません。
Windows Server 2008を運用している方にとっては自明なことかもしれませんが、Windows Server 2008の「Internet Explorer(IE)9」では、TLS 1.1/1.2を利用可能にするために、さらに追加の設定が必要でした。更新プログラムによりTLS 1.1/1.2のサポートが追加されたとしても、それだけでは「インターネットオプション」でTLS 1.1/1.2の使用を選択することはできません(画面5)。
次の場所にある「OSVersion」という名前の文字列値を削除することで、オプションを表示させることができます(画面6)。なお、32bit(x86)OSの場合は、「HKEY_LOCAL_MACHINE¥SOFTWARE¥Wow6432Node」のレジストリ値の削除は不要です。
HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.1
HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.2
HKEY_LOCAL_MACHINE¥SOFTWARE¥Wow6432Node¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.1
HKEY_LOCAL_MACHINE¥SOFTWARE¥Wow6432Node¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.2
コマンドラインからレジストリ値を削除するには、コマンドプロンプトまたはWindows PowerShellを管理者として開き、以下のコマンドラインを実行します。32bit(x86)OSの場合は、「HKLM¥SOFTWARE¥Wow6432Node」の下のレジストリの削除は不要です。
PS:¥> REG DELETE "HKLM¥SOFTWARE¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.1" /v OSVersion /f PS:¥> REG DELETE "HKLM¥SOFTWARE¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.2" /v OSVersion /f PS:¥> REG DELETE "HKLM¥SOFTWARE¥Wow6432Node¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.1" /v OSVersion /f PS:¥> REG DELETE "HKLM¥SOFTWARE¥Wow6432Node¥Microsoft¥Internet Explorer¥AdvancedOptions¥CRYPTO¥TLS1.2" /v OSVersion /f
岩手県花巻市在住。Microsoft MVP:Cloud and Datacenter Management(2019-2020)。SIer、IT出版社、中堅企業のシステム管理者を経て、フリーのテクニカルライターに。Microsoft製品、テクノロジーを中心に、IT雑誌、Webサイトへの記事の寄稿、ドキュメント作成、事例取材などを手掛ける。個人ブログは『山市良のえぬなんとかわーるど』。近著は『ITプロフェッショナル向けWindowsトラブル解決 コマンド&テクニック集』(日経BP社)。
Copyright © ITmedia, Inc. All Rights Reserved.