Подробный гайд: [Net.ServicePointManager]::SecurityProtocol возвращает 0
В .NET Framework перечисление System.Net.SecurityProtocolType не содержит значения 0. Когда свойство возвращает 0, это означает:
- Протоколы не заданы явно.
- .NET использует поведение по умолчанию (зависит от версии .NET и ОС).
- В старых версиях .NET Framework 0 интерпретировался как «разрешить все доступные, включая SSLv3/TLS1.0», что сегодня часто приводит к ошибкам подключения к современным серверам, требующим TLS 1.2/1.3.
Как проверить текущее состояние
# Текущее значение (битовая маска)
[Net.ServicePointManager]::SecurityProtocol
# Таблица всех доступных протоколов и их числовых значений
[Net.SecurityProtocolType].GetEnumValues() | Format-Table Name, Value
Пример вывода числовых значений:
| Имя | Значение |
|---|---|
| Ssl3 | 48 |
| Tls | 192 |
| Tls11 | 768 |
| Tls12 | 3072 |
| Tls13 | 12288 |
Как правильно настроить TLS 1.2 / TLS 1.3
Для PowerShell 5.1 (.NET Framework 4.x)
# Только TLS 1.2 (рекомендуемый минимум для 2024-2026)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# TLS 1.2 + TLS 1.3 (если ОС и .NET поддерживают)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13
Для PowerShell 7+ (.NET Core / .NET 5+)
В PowerShell 7+ ServicePointManager игнорируется для Invoke-WebRequest и Invoke-RestMethod, так как используется современный SocketsHttpHandler.
Начиная с PS 7.3, появился параметр -SslProtocol:
Invoke-WebRequest -Uri "https://example.com" -SslProtocol Tls12
# или
Invoke-WebRequest -Uri "https://example.com" -SslProtocol ([Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13)
Если вы видите 0 в PS 7+, это нормально и не влияет на работу HTTP-запросов.
Системные настройки (чтобы не писать в каждом скрипте)
1. Реестр для .NET Framework (глобально)
Создайте DWORD-параметр, чтобы .NET по умолчанию использовал сильные протоколы:
Путь: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319
Имя: SchUseStrongCrypto
Значение: 1
Для 32-битных приложений на 64-битной ОС:
Путь: HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319
Имя: SchUseStrongCrypto
Значение: 1
Требует перезапуска PowerShell/приложений.
2. Проверка поддержки TLS 1.3 в Windows
TLS 1.3 нативно поддерживается в:
- Windows 11 (22H2+)
- Windows Server 2022
- Windows 10 (21H2+) с обновлениями
Проверить можно через:
Test-Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3"
Как проверить, что TLS работает
try {
$resp = Invoke-WebRequest -Uri "https://www.howsmyssl.com/a/check" -UseBasicParsing
$json = $resp.Content | ConvertFrom-Json
Write-Host "Используемая версия: $($json.tls_version)" -ForegroundColor Green
} catch {
Write-Error "Ошибка подключения: $_"
}
Ожидаемый вывод:
TLS 1.2 или TLS 1.3.
Частые проблемы и решения
| Симптом | Причина | Решение |
|---|---|---|
The underlying connection was closed... |
Сервер требует TLS 1.2+, а у вас 0 или Tls1.0 |
Установите Tls12 явно |
| Значение не сохраняется после перезапуска | Свойство привязано к AppDomain (процессу) |
Добавляйте настройку в начало скрипта или в $PROFILE |
| В PS 7+ установка не меняет поведение | ServicePointManager устарел |
Используйте -SslProtocol или настройте ОС |
| Антивирус ломает TLS | старые шифры | Отключите проверку HTTPS на время теста |
| Ошибка в .NET < 4.6 | Нет поддержки TLS 1.2 из коробки | Установите .NET Framework 4.7+ или обновите ОС |
Best Practices (2024–2026)
- Не используйте
Tls(1.0) иSsl3– отключены на большинстве публичных серверов. - Устанавливайте
Tls12в начале скрипта или в$PROFILEдля PS 5.1. - Для PS 7+ полагайтесь на
-SslProtocolили системные настройки. - Для долгосрочных решений настраивайте TLS на уровне ОС/реестра, а не в скриптах.
- Проверяйте совместимость с целевыми сервисами через
howsmyssl.comилиtestssl.sh.
Готовый шаблон для PS 5.1
Добавьте в $PROFILE или в начало скриптов:
# Принудительный TLS 1.2 + 1.3 (если поддерживается)
if ([Enum]::GetNames([Net.SecurityProtocolType]) -contains 'Tls13') {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13
} else {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}