Статья
RDP 0x204: сеть жива, а виноват TLS private key
macOS Windows App пишет 0x204, порт 3389 слушается — TermService не может открыть закрытый ключ сертификата RDP.
С Mac подключаюсь к Windows через Windows App и получаю Error code: 0x204. Порт 3389 слушается, firewall открыт, TCP доходит — а сессия сразу рвётся. Оказалось: не Mac и не сеть, а сломанный доступ TermService к private key TLS-сертификата RDP.
Что произошло
На macOS Windows App:
We couldn't connect to the remote PC.
Error code: 0x204
На Windows при этом:
- RDP включён (
fDenyTSConnections = 0); 3389в состоянииListenуTermService;- в логе
RdpCoreTSвидно: TCP accepted → сразу terminated.
Как искал
Сначала отсёк очевидное: RDP включён, порт слушается, firewall пускает TCP 3389.
Главный сигнал — в System после неудачного коннекта:
Schannel 36870
A fatal error occurred when attempting to access the TLS server credential private key.
The SSPI client process is svchost[TermService].
Рядом:
TerminalServices-RemoteConnectionManager 1057
failed to create a new self signed certificate
Invalid algorithm specified
Иногда ещё 1059 — certificate configuration data was invalid.
Проверка привязки сертификата к RDP:
Get-CimInstance `
-Namespace root/cimv2/terminalservices `
-ClassName Win32_TSGeneralSetting `
-Filter "TerminalName='RDP-tcp'" |
Select-Object TerminalName,SSLCertificateSHA1Hash
По thumbprint сертификат в хранилище нашёлся, HasPrivateKey: True, но когда я реально открыл ключ:
$cert = Get-ChildItem Cert:\LocalMachine -Recurse |
Where-Object Thumbprint -eq '<THUMBPRINT>' |
Select-Object -First 1
[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
дало:
Keyset does not exist
То есть запись сертификата жива, а keyset уже нет или недоступен. Для RDP это фатально.
Решение
1. Новый сертификат в LocalMachine\My
New-SelfSignedCertificate нельзя класть сразу в Remote Desktop store — только в My.
$cert = New-SelfSignedCertificate `
-CertStoreLocation Cert:\LocalMachine\My `
-DnsName $env:COMPUTERNAME `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-KeyExportPolicy Exportable `
-NotAfter (Get-Date).AddYears(5) `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1")
$thumb = $cert.Thumbprint
$thumb
2. Права NETWORK SERVICE на private key
TermService обычно крутится от NT AUTHORITY\NETWORK SERVICE.
$cert = Get-ChildItem Cert:\LocalMachine\My |
Where-Object Thumbprint -eq $thumb |
Select-Object -First 1
$rsa = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
$keyPath = if ($rsa.GetType().FullName -eq 'System.Security.Cryptography.RSACng') {
Join-Path $env:ProgramData "Microsoft\Crypto\Keys\$($rsa.Key.UniqueName)"
} else {
$keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
Join-Path $env:ProgramData "Microsoft\Crypto\RSA\MachineKeys\$keyName"
}
icacls $keyPath /grant "NT AUTHORITY\NETWORK SERVICE:R"
3. Привязать thumbprint к RDP-Tcp и перезапустить службу
На части сборок метода SetSSLCertificateSHA1Hash нет — работает присваивание через WMI:
$ts = Get-WmiObject `
-Namespace root\cimv2\terminalservices `
-Class Win32_TSGeneralSetting `
-Filter "TerminalName='RDP-tcp'"
$ts.SSLCertificateSHA1Hash = $thumb
$ts.Put()
Restart-Service TermService -Force
Проверка:
Get-CimInstance `
-Namespace root/cimv2/terminalservices `
-ClassName Win32_TSGeneralSetting `
-Filter "TerminalName='RDP-tcp'" |
Select-Object TerminalName,SSLCertificateSHA1Hash
После удачного коннекта свежих Schannel 36870 и 1057/1059 быть не должно.
Итог
Если 0x204, TCP accepted, а потом сервер сам рвёт сессию и в System есть Schannel 36870 — почти наверняка виноват TLS/private key на стороне RDP, а не Mac-клиент.
Частые причины:
- подчистили ключи в
C:\ProgramData\Microsoft\Crypto; - слетели ACL;
- клон или snapshot VM;
- либо self-signed не пересоздался (
Invalid algorithm specified).