Files
fix-DAK-PC/scripts/Fix-RdpTls.ps1
T
PTah f35e2e2d96 fix: чтение SSLCertificateSHA1Hash через Registry API + версия 1.0.3
Усилена нормализация byte[]/Object[] из реестра; в логе версия модуля
для проверки git pull; RestoreTls нормализует thumbprint.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 21:13:56 +10:00

178 lines
8.0 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#Requires -Version 5.1
#Requires -RunAsAdministrator
<#
.SYNOPSIS
Локальная починка RDP TLS / сертификата TermService.
.PARAMETER DiagnoseOnly
Только диагностика и отчёт.
.PARAMETER EmergencyRdpOnly
SecurityLayer=0 (без TLS) для срочного доступа.
.PARAMETER RestoreTls
Вернуть SecurityLayer=2 после успешной привязки cert.
.PARAMETER SkipReboot
Не предлагать reboot при нативном сбросе.
.PARAMETER NonInteractive
Без вопросов (для автоматизации). $env:RDP_REPAIR_NONINTERACTIVE=1
#>
[CmdletBinding()]
param(
[switch]$DiagnoseOnly,
[switch]$EmergencyRdpOnly,
[switch]$RestoreTls,
[switch]$SkipReboot,
[switch]$NonInteractive
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
if ($NonInteractive) { $env:RDP_REPAIR_NONINTERACTIVE = '1' }
$libDir = Join-Path $PSScriptRoot 'lib'
. (Join-Path $libDir 'RdpRepair.Common.ps1')
$logPath = Join-Path (Initialize-RdpRepairDataRoot) ("repair-{0:yyyyMMdd-HHmmss}.log" -f (Get-Date))
function Show-RdpRepairClientCacheHint {
Write-RdpRepairLog 'На клиенте RDP выполните:' 'INFO' $logPath
Write-RdpRepairLog ' Remove-Item "HKCU:\Software\Microsoft\Terminal Server Client\Servers\<имя-сервера>" -Recurse -Force' 'INFO' $logPath
}
try {
Assert-RdpRepairAdministrator
Write-RdpRepairLog "=== Fix-RdpTls start $(Get-Date -Format o) (RdpRepair $($script:RdpRepairModuleVersion)) ===" 'STEP' $logPath
Write-RdpRepairLog "Компьютер: $env:COMPUTERNAME" 'INFO' $logPath
$report = Export-RdpRepairDiagnosticReport -LogPath $logPath
Write-RdpRepairLog "Диагностика сохранена: $report" 'OK' $logPath
if ($DiagnoseOnly) {
Get-RdpRepairDiagnosticSnapshot | Format-List
exit 0
}
if ($EmergencyRdpOnly) {
Write-RdpRepairLog 'ЭКСТРЕННЫЙ РЕЖИМ: SecurityLayer=0 (RDP без TLS)' 'WARN' $logPath
Set-RdpRepairSecurityLayer -Layer 0 -LogPath $logPath
Show-RdpRepairClientCacheHint
Write-RdpRepairLog 'Проверьте RDP. Для TLS после repair install: .\Fix-RdpTls.ps1 -RestoreTls' 'OK' $logPath
exit 0
}
if ($RestoreTls) {
Write-RdpRepairLog 'Возврат SecurityLayer=2 (TLS)' 'STEP' $logPath
$certs = @(Get-RdpRepairRemoteDesktopCertificates)
if ($certs.Count -eq 0) {
Write-RdpRepairLog 'No cert in Remote Desktop store - run full repair or repair install first' 'ERROR' $logPath
exit 2
}
$valid = @(Get-RdpRepairCertificateArray $certs | Where-Object { $_.NotAfter -gt (Get-Date) })[0]
if (-not $valid) {
Write-RdpRepairLog 'Все cert просрочены' 'ERROR' $logPath
exit 2
}
$thumb = ConvertTo-RdpRepairThumbprintHex -HashValue $valid.Thumbprint
if (-not $thumb) { throw 'Invalid certificate thumbprint' }
if (-not (Get-RdpRepairSslCertificateHash)) {
Write-RdpRepairLog "Привязка $thumb..." 'INFO' $logPath
Set-RdpRepairCertificateBinding -Thumbprint $thumb -LogPath $logPath | Out-Null
}
$bind = Test-RdpRepairCertificateBindingPersisted -ExpectedThumbprint $thumb -LogPath $logPath
if (-not $bind.Persisted) {
Write-RdpRepairLog 'TermService does not keep hash - cannot restore TLS. See docs\REPAIR-INSTALL.md' 'ERROR' $logPath
exit 3
}
Set-ItemProperty -Path $script:RdpRepairRdpTcpKey -Name SecurityLayer -Value 2
Restart-RdpRepairTermService
Write-RdpRepairLog 'SecurityLayer=2, TermService перезапущен' 'OK' $logPath
Show-RdpRepairClientCacheHint
exit 0
}
# --- Полный интерактивный ремонт ---
Write-RdpRepairLog 'ФАЗА 1: текущее состояние' 'STEP' $logPath
$snap = Get-RdpRepairDiagnosticSnapshot
$snap | Format-List ComputerName, OsCaption, SecurityLayer, SslHash, CertCount, Events1057_24h, GpoLicenseSrv
$expired = @(Get-RdpRepairCertificateArray $snap.Certificates | Where-Object { $_.NotAfter -lt (Get-Date) })
if ($expired.Count -gt 0) {
Write-RdpRepairLog "Найдено просроченных cert: $($expired.Count)" 'WARN' $logPath
}
if (-not (Confirm-RdpRepairContinue 'Продолжить: очистка cert и нативный сброс?')) {
exit 0
}
Write-RdpRepairLog 'ФАЗА 2: очистка stores + нативный сброс' 'STEP' $logPath
$native = Invoke-RdpRepairNativeReset -LogPath $logPath
if ($native.CertCount -gt 0) {
Write-RdpRepairLog "После сброса без reboot: нативный cert найден ($($native.CertCount))" 'OK' $logPath
$nativeCert = Get-RdpRepairFirstCertificate -Certificates $native.Certificates
if (-not $nativeCert) { throw 'Native cert list empty after reset' }
$bindNative = Test-RdpRepairCertificateBindingPersisted -ExpectedThumbprint $nativeCert.Thumbprint -LogPath $logPath
if ($bindNative.Persisted) {
Write-RdpRepairLog 'Native cert accepted - you can use RestoreTls' 'OK' $logPath
if (Confirm-RdpRepairContinue 'Установить SecurityLayer=2 сейчас?') {
Set-ItemProperty -Path $script:RdpRepairRdpTcpKey -Name SecurityLayer -Value 2
Restart-RdpRepairTermService
}
Show-RdpRepairClientCacheHint
exit 0
}
}
if (-not $SkipReboot -and (Confirm-RdpRepairContinue 'Нативный cert не прижился. Запланировать REBOOT через 60 с?')) {
Invoke-RdpRepairNativeReset -LogPath $logPath -Reboot | Out-Null
Write-RdpRepairLog 'После загрузки снова запустите: .\Fix-RdpTls.ps1' 'WARN' $logPath
exit 0
}
if (-not (Confirm-RdpRepairContinue 'ФАЗА 3: создать локальный cert и привязать?')) {
exit 0
}
Write-RdpRepairLog 'ФАЗА 3: создание cert' 'STEP' $logPath
Clear-RdpRepairCertificateStores -LogPath $logPath
$dns = @(Get-RdpRepairComputerDnsNames)
Write-RdpRepairLog "DNS: $($dns -join ', ')" 'INFO' $logPath
$cert = New-RdpRepairSelfSignedCertificate -DnsNames $dns -LogPath $logPath
Write-RdpRepairLog 'ФАЗА 4: ACL + Remote Desktop store' 'STEP' $logPath
Set-RdpRepairPrivateKeyAcl -Certificate $cert -LogPath $logPath | Out-Null
Add-RdpRepairCertificateToRemoteDesktopStore -Certificate $cert
Write-RdpRepairLog 'ФАЗА 5: привязка и проверка AFTER' 'STEP' $logPath
Set-RdpRepairCertificateBinding -Thumbprint $cert.Thumbprint -LogPath $logPath | Out-Null
$bind = Test-RdpRepairCertificateBindingPersisted -ExpectedThumbprint $cert.Thumbprint -LogPath $logPath
if ($bind.Persisted) {
if (Confirm-RdpRepairContinue 'Привязка OK. Установить SecurityLayer=2?') {
Set-ItemProperty -Path $script:RdpRepairRdpTcpKey -Name SecurityLayer -Value 2
Restart-RdpRepairTermService
}
Show-RdpRepairClientCacheHint
Write-RdpRepairLog '=== Ремонт TLS завершён успешно ===' 'OK' $logPath
exit 0
}
Write-RdpRepairLog '=== TermService отклоняет cert ===' 'ERROR' $logPath
Write-RdpRepairLog 'Варианты:' 'WARN' $logPath
Write-RdpRepairLog ' 1) docs\REPAIR-INSTALL.md - repair install Windows' 'WARN' $logPath
Write-RdpRepairLog ' 2) .\Fix-RdpTls.ps1 -EmergencyRdpOnly - RDP without TLS' 'WARN' $logPath
if (Confirm-RdpRepairContinue 'Включить Emergency SecurityLayer=0 сейчас?') {
Set-RdpRepairSecurityLayer -Layer 0 -LogPath $logPath
Show-RdpRepairClientCacheHint
}
exit 4
} catch {
Write-RdpRepairLog "FATAL: $($_.Exception.Message)" 'ERROR' $logPath
Write-RdpRepairLog $_.ScriptStackTrace 'ERROR' $logPath
exit 1
}