Перестали работать удаленные рабочие места. Следующая ошибка:
103 Критическое Microsoft-Windows-TerminalServices-Gateway Microsoft-Windows-TerminalServices-Gateway/Operational 15.03.2014 20:54:34
Службе шлюза удаленных рабочих столов не предоставлены разрешения, необходимые для доступа к SSL-сертификату, который требуется для приема подключений. Чтобы устранить эту проблему, свяжите (сопоставьте) действительный SSL-сертификат при помощи диспетчера шлюза удаленных рабочих столов. Дополнительные сведения см. в разделе справки диспетчера «Получение сертификата для сервера шлюза удаленных рабочих столов». Произошла следующая ошибка: «2148073494».
Вот еще какая-то общая ошибка:
В сети: счетчики производительности не запущены 15.03.2014 21:29:58 00183-90000-00001-AA422 (активировано)
единственное что приходит в ум — проблема появилась после смены коммутатора.
Перестали работать удаленные рабочие места. Следующая ошибка:
103 Критическое Microsoft-Windows-TerminalServices-Gateway Microsoft-Windows-TerminalServices-Gateway/Operational 15.03.2014 20:54:34
Службе шлюза удаленных рабочих столов не предоставлены разрешения, необходимые для доступа к SSL-сертификату, который требуется для приема подключений. Чтобы устранить эту проблему, свяжите (сопоставьте) действительный SSL-сертификат при помощи диспетчера шлюза удаленных рабочих столов. Дополнительные сведения см. в разделе справки диспетчера «Получение сертификата для сервера шлюза удаленных рабочих столов». Произошла следующая ошибка: «2148073494».
Вот еще какая-то общая ошибка:
В сети: счетчики производительности не запущены 15.03.2014 21:29:58 00183-90000-00001-AA422 (активировано)
единственное что приходит в ум — проблема появилась после смены коммутатора.
Posted by TDavidG 2017-12-29T20:07:17Z
Hey all I am trying to fix the following error in Server 2016:
Text
APP 103 Critical Microsoft-Windows-TerminalServices-Gateway Microsoft-Windows-TerminalServices-Gateway/Operational 12/29/2017 12:53:08 AM
I have already done the step by step located here and it seems to not have helped (I had «read«already selected for them all).
What else could be causing this?
2 Replies
-
Do you have the right cert selected in the gateway manager?
Was this post helpful?
thumb_up
thumb_down
Read these next…
-
Which network diagram (SAN to LAN) would you say is correct?
Networking
Which is best practice and why? Is it done one way over the other to avoid potential issues or is it just good housekeeping . . . or both?Edit for context . . . To the left — 3-node Hyper-V failover cluster connected to shared dual-controller storage via …
-
What kind of logs, data, or tooling do you have that need better visibility?
Windows
Hey,
I was part of a mass lay off awhile back, I am looking for work and
solutions to keep me busy while I continue to apply for jobs. Before I
was laid off I put together a small app that aggregated a lot of data
from GitLab with a simple sea… -
Snap! — Keyboard Hat, Emotional AI, US High-Speed Trains, Astronaut Wears Prada
Spiceworks Originals
Your daily dose of tech news, in brief.
Welcome to the Snap!
Flashback: October 6, 1942: Photocopying Patented (Read more HERE.)
Bonus Flashback: October 6, 1992: US-Russia Human Spaceflight Agreement (Read more HERE.)
You need to hear…
-
Time Clocks
Hardware
We’re looking for a solution that would allow clients who participate in certain services to punch in and punch out on a time clock with a PIN versus fingerprint or prox card. We’d prefer the solution to be entirely local versus cloud based. We did look…
-
Alternative to Sophos central
Security
Hi there, I am a Sophos partner and currently have clients that run Sophos Essentials on their work machines — and it looks like our licenses are due for expiry soon. Would you guys suggest any alternative vendors that offer the same functionality as Soph…
First published on TechNet on Apr 20, 2009
[Today’s post comes to us courtesy of
Chris Puckett
]
When you select the server and click Restart in the IIS Manager console, the Terminal Services Gateway service will be stopped and not restarted, even though the World Wide Web Publishing service is restarted. If you are logged into the server via RWW or a TS Gateway session, your connection will be dropped and you will not be able to get back in via RWW or TS Gateway. In addition, the following event will be logged in the Microsoft-Windows-TerminalServices-Gateway/Operational log.
Log Name: Microsoft-Windows-TerminalServices-Gateway/Operational
Source: Microsoft-Windows-TerminalServices-Gateway
Event ID: 400
Task Category: (3)
Level: Warning
Keywords: (16777216)
User: NETWORK SERVICE
Computer: SBS2008.CONTOSO.LOCAL
Description:
The TS Gateway service is shutting down. To diagnose possible causes for this problem, verify whether the following services are installed and started: (1) World Wide Web Publishing Service (2) Internet Authentication Service (IAS) (3) RPC/HTTP Load Balancing Service. Also, check Event Viewer for Network Policy Server (NPS) and IIS events that might indicate problems with NPS or IIS.
Keep this in my mind when working in IIS Manager on the SBS server remotely. Use
iisreset /noforce
instead or
restart
the
World Wide Web Publishing
service in the Services console.
- Remove From My Forums
-
Общие обсуждения
-
Перестали работать удаленные рабочие места. Следующая ошибка:
103 Критическое Microsoft-Windows-TerminalServices-Gateway Microsoft-Windows-TerminalServices-Gateway/Operational 15.03.2014 20:54:34
Службе шлюза удаленных рабочих столов не предоставлены разрешения, необходимые для доступа к SSL-сертификату, который требуется для приема подключений. Чтобы устранить эту проблему, свяжите (сопоставьте) действительный SSL-сертификат при помощи
диспетчера шлюза удаленных рабочих столов. Дополнительные сведения см. в разделе справки диспетчера «Получение сертификата для сервера шлюза удаленных рабочих столов». Произошла следующая ошибка: «2148073494».
Проблема
При попытке создания цифровой подписи PDF в Adobe Acrobat 8 или 9 для Windows приложение возвращает сообщение об ошибке: «Не удалось закончить создание этой подписи. Исключение на уровне платформы». Вслед за сообщением об ошибке находится одно из этих выражений:
- «Объект уже существует. Код ошибки: 2148073487»
- «Keyset не существует. Код ошибки: 2148073494»
- «Ключ недействителен для использования в указанном состоянии. Код ошибки: 2148073483″
Решение. Повторно создайте цифровое удостоверение и/или папку Crypto
Используйте одно или оба из предлагаемых решений:
Повторно создайте цифровое удостоверение
-
Выберите пункт меню «Дополнительно» > «Настройки безопасности».
-
В списке «Категории» в левой части окна «Настройки безопасности» выберите «Цифровое удостоверение».
-
Выберите цифровое удостоверение, с помощью которого вы пытались подписать файл PDF.
-
Нажмите кнопку «Удалить идентификатор».
-
В диалоговом окне подтверждения нажмите «ОК».
-
Нажмите кнопку «Добавить идентификатор».
-
Следуйте инструкциям на экране для воссоздания цифрового удостоверения.
Повторно создайте папку Crypto
-
Выполните одно из следующих действий в Проводнике Windows:
- В системе Windows XP перейдите к папке C:Documents and Settings[имя-пользователя]Application DataMicrosoft.
- В системе Windows Vista перейдите к папке C:Users[имя-пользователя]AppDataRoamingMicrosoft.
Примечание. Эти пути включают скрытые папки. Чтобы сделать скрытые папки видимыми, см. раздел «Отображение скрытых файлов и папок в ОС Windows 10 и более ранних версиях».
-
Переименовать папку Crypto в папку Crypto Old.
-
Откройте Acrobat. Папка Crypto будет автоматически создана заново.
Hi,
In all probability the digital ID has expired. There is an expiration date listed in the Security Settings dialog, what does it say? If the digital ID has indeed expired, and you would like to remove it from the Windows Certificate Store you need to do it through a Windows interface, not through Acrobat. Like many things, there are more then one way to go about this, but the simplest is to start Internet Explorer. From Internet Explorer select the Tools menu or button, and then Internet Options from the drop-down menu. Next, select the Contents tab on the Internet Option dialog and then click the Certificates button.
Here is where you’ll see the digital IDs loaded into the Windows Certificate Store. You can highlight the expired ID that you would like to delete and click the Remove button, BUT FIRST, I strongly suggest that you Export the ID to a file in case you ever need to get back to it for some reason. Think of this as escrowing or archiving the digital ID just in case. Once you’ve saved the digital ID to a file, then you can remove it knowing that you could resurrect it at some time in the future.
Of course, if it has expired you will need to procure a fresh digital ID if you want to continue to digitally sign PDF files, but that’s a separate discussion.
Steve
Hi,
In all probability the digital ID has expired. There is an expiration date listed in the Security Settings dialog, what does it say? If the digital ID has indeed expired, and you would like to remove it from the Windows Certificate Store you need to do it through a Windows interface, not through Acrobat. Like many things, there are more then one way to go about this, but the simplest is to start Internet Explorer. From Internet Explorer select the Tools menu or button, and then Internet Options from the drop-down menu. Next, select the Contents tab on the Internet Option dialog and then click the Certificates button.
Here is where you’ll see the digital IDs loaded into the Windows Certificate Store. You can highlight the expired ID that you would like to delete and click the Remove button, BUT FIRST, I strongly suggest that you Export the ID to a file in case you ever need to get back to it for some reason. Think of this as escrowing or archiving the digital ID just in case. Once you’ve saved the digital ID to a file, then you can remove it knowing that you could resurrect it at some time in the future.
Of course, if it has expired you will need to procure a fresh digital ID if you want to continue to digitally sign PDF files, but that’s a separate discussion.
Steve
Это исключение возникало периодически, когда наша служба приложений Azure была перемещена в среду службы приложений. Мы используем Identity Server 4, и исключение происходит при подписании токена. Это можно увидеть в стеке вызовов ниже.
Сертификат подписи никогда не сохраняется в хранилище сертификатов, он загружается из базы данных в виде байтового массива:
new X509Certificate2(rawData, password,
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
Эти ссылки кажутся одной и той же проблемой:
.NET Core X509Certificate2.PrivateKey выбрасывает ошибку nte_bad_keyset
https://github.com/dotnet/corefx/issues/2583
< Сильный > Edit: Изначально мы думали, что это что-то особенное для Env службы приложений в Azure, но теперь мы видим исключение в стандартных службах приложений. В качестве теста мы создали веб-задание Azure, которое загружает сертификат из байтового массива и создает токены JWT (для подписи которых требуется закрытый ключ). Это повторяет ошибку. Также следует отметить, что веб-задание Azure даже не запускается, когда определенные флаги передаются в X509Certificate2
ctor (например, X509KeyStorageFlags.UserKeySet
).
Трассировка стека каждый раз одинакова:
System.Security.Cryptography.CryptographicException:
at Internal.NativeCrypto.CapiHelper.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeProvHandle()
at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeKeyHandle()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 keySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters)
at Internal.Cryptography.Pal.CertificatePal.<>c.<GetRSAPrivateKey>b__59_0(CspParameters csp)
at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func`2 createCsp, Func`2 createCng)
at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()
at Internal.Cryptography.Pal.CertificateExtensionsCommon.GetPrivateKey[T](X509Certificate2 certificate, Predicate`1 matchesConstraints)
at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PrivateKey()
at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_HasPrivateKey()
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.HasPrivateKey(SecurityKey key)
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken token)
at IdentityServer4.Services.DefaultTokenCreationService.CreateJwtAsync(JwtSecurityToken jwt)
at IdentityServer4.Services.DefaultTokenCreationService.<CreateTokenAsync>d__3.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Services.DefaultTokenService.<CreateSecurityTokenAsync>d__9.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at IdentityServer4.ResponseHandling.TokenResponseGenerator.<CreateAccessTokenAsync>d__10.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.ResponseHandling.TokenResponseGenerator.<ProcessTokenRequestAsync>d__8.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.ResponseHandling.TokenResponseGenerator.<ProcessAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Endpoints.TokenEndpoint.<ProcessTokenRequestAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Endpoints.TokenEndpoint.<ProcessAsync>d__5.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.IdentityServerMiddleware.<Invoke>d__3.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.FederatedSignOutMiddleware.<Invoke>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.AuthenticationMiddleware.<Invoke>d__2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.<Invoke>d__7.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.BaseUrlMiddleware.<Invoke>d__2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware`1.<Invoke>d__18.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ApplicationInsights.AspNetCore.ExceptionTrackingMiddleware.<Invoke>d__4.MoveNext()
3 ответа
Лучший ответ
Чтобы решить эту проблему, мы переключились с сертификатов X509 (X509Certificate2
) на сгенерированные RSA ключи (RSACryptoServiceProvider
). Identity Server 4 поддерживает оба. Исключение больше не возникает.
1
J. Andrew Laughlin
7 Мар 2017 в 17:41
Эта ошибка означает, что где-то после того, как сертификат узнал, где хранится ключ, он был удален.
- Может быть, что-то вызывает CngKey.Delete
- Возможно, что-то клонирует это в RSACryptoServiceProvider и устанавливает
PersistKeyInCsp
вfalse
. - Может быть, что-то просто очищает каталог ключей машины после свершившегося факта.
- Другой (очень редкий) известный случай — это когда два потока загружают PFX параллельно (они не должны быть в одном и том же процессе), причем один из них не имеет
PersistKeySet
, заявленного во время импорта.
Если вы загружаете и удаляете сертификаты, вам не следует устанавливать PersistKeySet
. Каждый раз, когда вы открываете PFX, на диске для каждого содержащегося в нем закрытого ключа создается другой файл … эти файлы очищаются нормально (до тех пор, пока процесс не завершается ненормально), но PersistKeySet предотвращает эту очистку.
Если ничто в анализе кода не выявит два очевидных местоположения удаления ключей (PersistKeyInCsp=false
— хитрое), вам придется следовать рекомендациям по аудиту файловой системы в . NET Core X509Certificate2.PrivateKey выдает ошибку nte_bad_keyset .
0
Community
23 Май 2017 в 12:02
Возможно, вы не предоставили IIS доступ к своим закрытым ключам. У меня была такая же ошибка, но вместо ключей нужно было использовать сертификаты X509. Я только что дал разрешение на чтение закрытых ключей из сертификата для IIS_IUSRS на MMC. Это помогает мне.
Полный ответ от @thames
: Как предоставить ASP.NET доступ к закрытому ключу в сертификате в хранилище сертификатов?
< Сильный > UPD :
Пошаговое руководство:
- Создать / купить сертификат с закрытым ключом
- Импортируйте сертификат в учетную запись «Локальный компьютер» (не «Текущий пользователь»). Установите флажок «Разрешить экспорт закрытого ключа» в мастере импорта.
- Откройте консоль MMC и добавьте оснастку «Сертификаты». Выберите «Учетная запись компьютера».
- Найдите свой сертификат и щелкните по нему правой кнопкой мыши. Выберите «Все задачи»> «Управление личными ключами»
- Добавьте доступ на чтение к своему ключу для пользователя IIS_IUSRS или IIS AppPool (зависит от версии и конфигурации IIS. Для отображения всех возможных параметров лучше использовать кнопку «Дополнительно»)
- Перезапустите ваше приложение
0
Eugene Voynov
26 Июл 2017 в 13:39
Мы начали видеть, что это исключение происходит с перерывами, когда наша служба приложений Azure перенесена в среду обслуживания приложений. Мы используем Identity Server 4, и исключение происходит во время подписания токена. Это можно увидеть в стеке вызовов ниже.
Сертификат подписи никогда не сохраняется в хранилище сертификатов, он загружается из базы данных в виде массива байтов:
new X509Certificate2(rawData, password,
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
Эти ссылки выглядят одинаково:
.NET Core X509Certificate2.PrivateKey вызывает ошибку nte_bad_keyset
https://github.com/dotnet/corefx/issues/2583
Edit: Первоначально мы думали, что это что-то особенное для App App Env в Azure, но теперь мы видим исключение в стандартных приложениях. В качестве теста мы создали веб-задачу Azure, которая загружает сертификат из массива байтов и создает токены JWT (для которых требуется закрытый ключ для подписи). Это повторяет ошибку. Также следует отметить, что работа Azure Web даже не запускается, когда определенные флаги передаются в X509Certificate2
ctor (например, X509KeyStorageFlags.UserKeySet
).
Трассировка стека одинакова каждый раз:
System.Security.Cryptography.CryptographicException:
at Internal.NativeCrypto.CapiHelper.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeProvHandle()
at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeKeyHandle()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 keySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters)
at Internal.Cryptography.Pal.CertificatePal.<>c.<GetRSAPrivateKey>b__59_0(CspParameters csp)
at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func'2 createCsp, Func'2 createCng)
at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()
at Internal.Cryptography.Pal.CertificateExtensionsCommon.GetPrivateKey[T](X509Certificate2 certificate, Predicate'1 matchesConstraints)
at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PrivateKey()
at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_HasPrivateKey()
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.HasPrivateKey(SecurityKey key)
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken token)
at IdentityServer4.Services.DefaultTokenCreationService.CreateJwtAsync(JwtSecurityToken jwt)
at IdentityServer4.Services.DefaultTokenCreationService.<CreateTokenAsync>d__3.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Services.DefaultTokenService.<CreateSecurityTokenAsync>d__9.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at IdentityServer4.ResponseHandling.TokenResponseGenerator.<CreateAccessTokenAsync>d__10.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.ResponseHandling.TokenResponseGenerator.<ProcessTokenRequestAsync>d__8.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.ResponseHandling.TokenResponseGenerator.<ProcessAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Endpoints.TokenEndpoint.<ProcessTokenRequestAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Endpoints.TokenEndpoint.<ProcessAsync>d__5.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.IdentityServerMiddleware.<Invoke>d__3.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.FederatedSignOutMiddleware.<Invoke>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.AuthenticationMiddleware.<Invoke>d__2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware'1.<Invoke>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware'1.<Invoke>d__18.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.<Invoke>d__7.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at IdentityServer4.Hosting.BaseUrlMiddleware.<Invoke>d__2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware'1.<Invoke>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware'1.<Invoke>d__18.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware'1.<Invoke>d__18.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware'1.<Invoke>d__18.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ApplicationInsights.AspNetCore.ExceptionTrackingMiddleware.<Invoke>d__4.MoveNext()
При разворачивании минимальной конфигурации RDS на скорую руку, в очередной раз сталкиваюсь с проблемами и в очередной раз забываю как их решать. Первое что нужно сделать перед развертыванием это конечно прочитать best practices, а потом составить план. Выписать все что необходимо заранее, подготовить, запросить.
Например сертификат SSL и доменное имя типа remote.mycompany.ru (DNS запись A). Даже развертывая очень маленький терминальный сервер для очень маленькой компании имеет смысл прикупить SSL если планируется доступ из сети интернет. Сегодня удаленный доступ нужен только с одного ноутбука, а завтра потребуется еще на десятке смартфонов. Замучаешься устанавливать везде свой локальный сертификат в корневые. Тем более что SSL сертификат сейчас стоит копейки. Я последнее время беру на https://www.ssls.com/ , с кодом 3.88DEAL вообще копейки. И оплатить можно даже биткойнами. Проще всего запрос сертификата сделать установив на сервер роль IIS, тем более что он все равно потребуется для развертывания шлюза. В IIS есть раздел SSL, там визарды для создания запроса сертификата и для его установки (есть смысл запрашивать сертификат минимум 2048 bit ).
Часто сервер физически один, а службы удаленного доступа хотят иметь в своем составе шлюз, сервер лицензирования, сам терминальный сервер. Да и домен в ряде случаев не поднят. Технически возможна установка RDS на сервер в рабочей группе, но если есть возможность, можно сразу поднять контроллер домена. Если был куплен Windows Server Standard и выше, то его можно установить в двух экземплярах в виде виртуалок на одном физическом хосте. Если есть возможность — почему не использовать? Например DC аппаратный хост, а RDS на нем в Hyper-v. Или наоборот. Да DC в одном экземпляре, да еще и виртуальном, но ведь у нас нет 100500 ПК в этом домене. Всего один сервер и нужно просто иметь логины и пароли локальных админов.
В случае развертывания RDS в малом бизнесе очень часто IP адрес внешний один и нет возможности или желания докупать еще. В итоге создается конкуренция между внутренними сервисами за порты на этом IP. HTTP и HTTPS часто заняты другими ресурсами, и это создает массу проблем при развертывании RDS Gateway. Приходится переносить на другие порты, ручками местами прописывать потом эти порты.
Например, вместо 80 ставим 81, а вместо 443 — 442. Теряется красота ссылок на ресурсы, вместо https://remote.mycompany.ru/rdweb получаем https://remote.mycompany.ru:442/rdweb . Кроме того, наживаем кучу проблем с прописыванием этих самых 442 в разных местах. Есть пара решений, нашел на Windowsitpro.com. В оснастке диспетчера служб удаленных рабочих столов можно указать порты. Кроме того, для RemoteApp нужно тоже прописать порт, иначе приложения будут ссылаться на стандартный 443. Можно отредактировать реестр, указав порт:
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionTerminal ServerCentralPublishedResourcesPublishedFarms<farm>DeploymentSettings, в нем ищем DeploymentRDPSettings и добавляем к gatewayhostname:s:remote.mycompany.ru:442 номер порта. Сделать это нужно до того как опубликовали приложения RemoteApp, в противном случае приложения придется распубликовать и опубликовать повторно. Можно не реестром, а через PowerShell:
Set-RDSessionCollectionConfiguration –CollectionName «Your Collection» -CustomRdpProperty «gatewayhostname:s:<GATEWAY.FQDN>:<442>» -ConnectionBroker <Your Connection Broker>
Но у меня на эти часть команд PS ругался, считал что RDS не установлены на сервере.Часто возникает проблема с SSL и hostname. SSL мы получили вида remote.mycompany.ru, а сервер у нас что-то вроде rdsserver.mycompany.local . Поэтому при первых же подключениях можно получить как минимум предупреждение «Имя сервера отличается от имени указанного в сертификате». Это если мы конечно прописали сертификат везде где надо:
- Привязки в IIS к порту 442 (можно и к 443)
- В диспетчере серверов (Настройка развертывания служб удаленных рабочих столов)
- В диспетчере шлюза удаленных рабочих столов ( у меня не прописался сам, пришлось ручками).
В некоторых случаях предупреждение можно просто игнорировать. На некоторых платформах игнорировать нельзя.
Решить проблему можно либо командой:
Set-RDSessionCollectionConfiguration –CollectionName QuickSessionCollection -CustomRdpProperty “use redirection server name:i:1 `n alternate full address:s:remote.mycompany.ru”либо скриптом.
.Set-RDPublishedName.ps1 «remote.mycompany.ru:442»
Скрипт у меня сразу не запустился, нашел ряд решений, например —
powershell.exe -noprofile -executionpolicy bypass -file .Set-RDPublishedName.ps1
Я зачем-то еще настроил на DC DNS зону mycompany.ru, и в ней создал DNS запись A «remote.mycompany.ru», указывающую на внутренний адрес RDS сервера, но это скорее по привычке.
Все бы ничего, но как только мы решили проблему с несоответствием имени указанном в SSL сертификате и имени сервера к которому подключаемся, появляется другая проблема.
event 301:
Пользователь «mycompanyuser» на клиентском компьютере «8.8.8.8» не соответствует требованиям политики авторизации ресурсов и не авторизован для подключения к ресурсу «remote.mycompany.ru». Произошла следующая ошибка: «23002».
Дело в том что по умолчанию создаются политики удаленного доступа для штатной ситуации. А мы уже подправили скриптом, реестром, имя сервера к которому ведется подключение. И в политиках ничего не написано про remote.mycompany.ru. Открываем диспетчер шлюза удаленных рабочих столов и правим политику — добавляем туда наш адрес remote.mycompany.ru.
В первой части статьи (Кто и когда подключался по RDP) я в конце говорил, что скрипт не записывает ip адрес подключившегося, но при просмотре логов, ip адрес очень легко получить.
Подключение средствами RDP.
Необходимо просмотреть логи Microsoft-Windows-TerminalServices-RemoteConnectionManager по событию 1149, что бы получить возможность сопоставить пользователя с ip адресом. По умолчанию, логи настроены на малое количество записей, поэтому не забываем настроить максимальный объем журнала.
Сам скрипт выглядит вот так:
Get-WinEvent «Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational» | ?{$_.ID -eq «1149»} | %{ New-Object PSObject -Property @{ MachineName = $_.MachineName TimeCreated = $_.TimeCreated User = $_.Properties[0].Value Domain = $_.Properties[1].Value SourceIP = $_.Properties[2].Value } }| Out-GridView |
Данный скрипт необходимо запускать на терминальном сервере.
Подключение средствами RDG.
В случае если используется подключение через защищенное соединение — RDG (Remote Desktop Gateway), то необходимо обратиться к логам Microsoft-Windows-TerminalServices-Gateway, которые так же необходимо настроить на максимальный объем хранения.
300 — The user «%1», on client computer «%2», met resource authorization policy requirements and was therefore authorized to connect to resource «%4».
302 — The user «%1», on client computer «%2», connected to resource «%4».
303 — The user «%1», on client computer «%2», disconnected from the following network resource: «%4». Before the user disconnected, the client transferred %6 bytes and received %5 bytes. The client session duration was %7 seconds.
Источник: MS
В итоге получаем вот такой скрипт:
$Events = Get-WinEvent -FilterHashtable @{Logname = «Microsoft-Windows-TerminalServices-Gateway/Operational» ; ID = 300,302,303 } $date = Get-Date -format yyyy-MM-dd $ArrayList = New-Object System.Collections.ArrayList Foreach ($Event in $Events) { [xml]$Xml = $Event.ToXml() $Row = «» | Select Username,TimeCreated,IPAddress $Row.Username = $Xml.Event.UserData.EventInfo.Username $Row.TimeCreated = $Event.TimeCreated.ToString() $Row.IPAddress = $Xml.Event.UserData.EventInfo.IpAddress [void]$ArrayList.Add($Row) } $ArrayList | export-csv C:\LogFile\$date.csv -nti |
P.S.
Уже даже нарисовал формочку для скрипта:
Но это уже тема для другой статьи. 🙂
В этой статье мы рассмотрим, как получить и проанализировать логи RDP подключений в Windows. Логи RDP подключений позволяют администраторам терминальных RDS серверов/ферм получить информацию о том, какие пользователи подключались к серверу, когда был выполнен вход и когда сеанс завершен, с какого устройства (имя или IP адрес) подключался пользователь.
Описанные методики получения и исследования RDP логов применима как к Windows Server 2022/2019/2016/2012R2, так и для десктопных версий Windows 11, 10, 8.1 c.
Содержание:
- События RDP подключений в журналах Windows (Event Viewer)
- Получаем логи RDP подключений в Windows с помощью PowerShell
- Логи RDP подключений на клиентах Windows
События RDP подключений в журналах Windows (Event Viewer)
Когда пользователь удаленно подключается к RDS серверу или удаленному столу Windows (RDP), информация об этих событиях сохраняется в журналы Windows. Рассмотрим основные этапы RDP подключения и связанные с ними события в Event Viewer.
- Network Connection
- Authentication
- Logon
- Session Disconnect/Reconnect
- Logoff
Network Connection: – событие установления сетевого подключение к серверу от RDP клиента пользователя. Событие с EventID – 1149 (Remote Desktop Services: User authentication succeeded). Наличие этого события не свидетельствует об успешной аутентификации пользователя. Этот журнал находится в разделе Applications and Services Logs -> Microsoft -> Windows -> Terminal-Services-RemoteConnectionManager -> Operational. Включите фильтр по данному событию (ПКМ по журналу-> Filter Current Log -> EventId 1149).
С помощью PowerShell можно вывести список всех попыток RDP подключений:
$RDPAuths = Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational' -FilterXPath '<QueryList><Query Id="0"><Select>*[System[EventID=1149]]</Select></Query></QueryList>'
[xml[]]$xml=$RDPAuths|Foreach{$_.ToXml()}
$EventData = Foreach ($event in $xml.Event)
{ New-Object PSObject -Property @{
TimeCreated = (Get-Date ($event.System.TimeCreated.SystemTime) -Format 'yyyy-MM-dd hh:mm:ss K')
User = $event.UserData.EventXML.Param1
Domain = $event.UserData.EventXML.Param2
Client = $event.UserData.EventXML.Param3
}
} $EventData | FT
В результате у вас получится список с историей всех сетевых RDP подключений к данному серверу. В событии содержится имя пользователя, домен (если используется NLA аутентификация, при отключенном NLA текст события выглядит иначе) и IP адрес компьютера пользователя.
Authentication: – успешная или неудачная аутентификация пользователя на сервере. Журнал Windows -> Security. Здесь нас могут интересовать события с EventID – 4624 (успешная аутентификация — An account was successfully logged on) или 4625 (ошибка аутентификации — An account failed to log on). Обратите внимание на значение LogonType в событии.
- LogonType = 10 или 3 — при входе через терминальную службу RDP —.
- LogonType = 7, значит выполнено переподключение к уже существующему RDP сеансу.
- LogonType = 5 – событие RDP подключения к консоли сервера (в режиме mstsc.exe /admin)
Вы можете использовать события с ошибками аутентификации для защиты от удаленного перебора паролей через RDP. СВы можете автоматически блокировать на файерволе IP адреса, с которых выполняется подбор пароля, простым PowerShell скриптом (см. статью).
При этом имя пользователя содержится в описании события в поле Account Name, имя компьютера в Workstation Name, а имя пользователя в Source Network Address.
Обратите внимание на значение поля LogonID – это уникальный идентификатор сессии пользователя, с помощью которого можно отслеживать дальнейшую активность данного пользователя. Но при отключении от RDP сессии (disconnect) и повторного переподключения к той же сессии, пользователю будет выдан новый TargetLogonID (хотя RDP сессия осталась той же самой).
Вы можете получить список событий успешных авторизаций по RDP (событие 4624) с помощью такой команды PowerShell.
Get-EventLog security -after (Get-date -hour 0 -minute 0 -second 0) | ?{$_.eventid -eq 4624 -and $_.Message -match 'logon type:\s+(10)\s'} | Out-GridView
Logon: – RDP вход в систему, EventID – 21 (Remote Desktop Services: Session logon succeeded. Это событие появляется после успешной аутентификации пользователя. Этот журнал находится в разделе Applications and Services Logs -> Microsoft -> Windows -> TerminalServices-LocalSessionManager -> Operational. Как вы видите, здесь можно узнать идентификатор RDP сессии для пользователя — Session ID.
Событие с EventID – 21 (Remote Desktop Services: Shell start notification received) означает успешный запуск оболочки Explorer (появление окна рабочего стола в RDP сессии).
Session Disconnect/Reconnect – события отключения и переподключения к сессии имеют разные коды в зависимости от того, что вызвало отключение пользователя (отключение по неактивности, заданному в таймаутах для RDP сессий; выбор пункта Disconnect в сессии; завершение RDP сессии другим пользователем или администратором и т.д.). Эти события находятся в разделе журналов Applications and Services Logs -> Microsoft -> Windows -> TerminalServices-LocalSessionManager -> Operational. Рассмотрим RDP события, которые могут быть полезными:
- EventID – 24 (Remote Desktop Services: Session has been disconnected) – пользователь отключился от RDP сессии.
- EventID – 25 (Remote Desktop Services: Session reconnection succeeded) – пользователь переподключился к своей имеющейся RDP сессии на сервере.
- EventID – 39 (Session <A> has been disconnected by session <B>) – пользователь сам отключился от своей RDP сессии, выбрав соответствующий пункт меню (а не просто закрыл окно RDP клиента). Если идентификаторы сессий разные, значит пользователя отключил другой пользователь (или администратор).
- EventID – 40 (Session <A> has been disconnected, reason code <B>). Здесь нужно смотреть на код причины отключения в событии. Например:
- reason code 0 (No additional information is available) – обычно говорит о том, что пользователь просто закрыл окно RDP клиента.
- reason code 5 (The client’s connection was replaced by another connection) – пользователь переподключился к своей старой сессии.
- reason code 11 (User activity has initiated the disconnect) – пользователь сам нажал на кнопку Disconnect в меню.
Событие с EventID – 4778 в журнале Windows -> Security (A session was reconnected to a Window Station). Пользователь переподключился к RDP сессии (пользователю выдается новый LogonID).
Событие с EventID 4779 в журнале Windows -> Security (A session was disconnected from a Window Station). Отключение от RDP сеанса.
Logoff: – выход пользователя из системы. При этом в журнале Applications and Services Logs -> Microsoft -> Windows -> TerminalServices-LocalSessionManager -> Operational регистрируется событие с EventID 23 (Remote Desktop Services: Session logoff succeeded).
При этом в журнале Security нужно смотреть событие EventID 4634 (An account was logged off).
Событие Event 9009 (The Desktop Window Manager has exited with code (<X>) в журнале System говорит о том, что пользователь инициировал завершение RDP сессии, и окно и графический shell пользователя был завершен.
EventID 4647 — User-initiated logoff
Получаем логи RDP подключений в Windows с помощью PowerShell
Ниже представлен небольшой PowerShell скрипт, который выгружает из журналов терминального RDS сервера историю всех RDP подключений за текущий день. В полученной таблице указано время подключения, IP адрес клиента и имя пользователя (при необходимости вы можете включить в отчет другие типы входов).
Get-EventLog -LogName Security -after (Get-date -hour 0 -minute 0 -second 0)| ?{(4624,4778) -contains $_.EventID -and $_.Message -match 'logon type:\s+(10)\s'}| %{
(new-object -Type PSObject -Property @{
TimeGenerated = $_.TimeGenerated
ClientIP = $_.Message -replace '(?smi).*Source Network Address:\s+([^\s]+)\s+.*','$1'
UserName = $_.Message -replace '(?smi).*\s\sAccount Name:\s+([^\s]+)\s+.*','$1'
UserDomain = $_.Message -replace '(?smi).*\s\sAccount Domain:\s+([^\s]+)\s+.*','$1'
LogonType = $_.Message -replace '(?smi).*Logon Type:\s+([^\s]+)\s+.*','$1'
})
} | sort TimeGenerated -Descending | Select TimeGenerated, ClientIP `
, @{N='Username';E={'{0}\{1}' -f $_.UserDomain,$_.UserName}} `
, @{N='LogType';E={
switch ($_.LogonType) {
2 {'Interactive - local logon'}
3 {'Network conection to shared folder)'}
4 {'Batch'}
5 {'Service'}
7 {'Unlock (after screensaver)'}
8 {'NetworkCleartext'}
9 {'NewCredentials (local impersonation process under existing connection)'}
10 {'RDP'}
11 {'CachedInteractive'}
default {"LogType Not Recognised: $($_.LogonType)"}
}
}}
Можно экспортировать логи RDP подключений из журнала в CSV файл (для дальнейшего анализа в таблице Excel). Экспорт журнала можно выполнить из консоли Event Viewer (при условии что логи не очищены) или через командную строку:
WEVTUtil query-events Security > c:\ps\security_log.txt
Или с помощью PowerShell:
get-winevent -logname "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" | Export-Csv c:\ps\rdp-log.csv -Encoding UTF8
Если ваши пользователи подключаются к RDS серверам через шлюз удаленных рабочих столов Remote Desktop Gateway, вы можете обрабатывать логи подключений пользователей по журналу Microsoft-Windows-TerminalServices-Gateway по EventID 302. Например, следующий PowerShell скрипт выведет полную историю подключений через RD Gateway указанного пользователя:
$rdpusername="kbuldogov"
$properties = @(
@{n='User';e={$_.Properties[0].Value}},
@{n='Source IP Adress';e={$_.Properties[1].Value}},
@{n='TimeStamp';e={$_.TimeCreated}}
@{n='Target RDP host';e={$_.Properties[3].Value}}
)
(Get-WinEvent -FilterHashTable @{LogName='Microsoft-Windows-TerminalServices-Gateway/Operational';ID='302'} | Select-Object $properties) -match $rdpusername
Другие события, связанные с подключениями пользователей на RD Gateway в журнале Microsoft-Windows-TerminalServices-Gateway:
- 300 —
The user %1, on client computer %2, met resource authorization policy requirements and was therefore authorized to connect to resource %4
- 302 —
The user %1, on client computer %2, connected to resource %4
- 303 —
The user %1, on client computer %2, disconnected from the following network resource: %4. Before the user disconnected, the client transferred %6 bytes and received %5 bytes. The client session duration was %7 seconds.
Список текущих RDP сессий на сервере можно вывести командой:
qwinsta
Команда возвращает как идентификатор сессии (ID), имя пользователя (USERNAME)и состояние (Active/Disconnect). Эту команду удобна использовать, когда нужно определить ID RDP сессии пользователя при теневом подключении.
Список запущенных процессов в конкретной RDP сессии (указывается ID сессии):
qprocess /id:157
Логи RDP подключений на клиентах Windows
Также вы можете изучать логи исходящих подключений на стороне RDP клиента. Они доступны в журнале событий Application and Services Logs -> Microsoft -> Windows -> TerminalServices-ClientActiveXCore -> Microsoft-Windows-TerminalServices-RDPClient -> Operation.
Например, событие с Event ID 1102 появляется, когда компьютер устанавливает подключение с удаленным RDS хостом Windows Server или компьютером с Windows 10/11 с включенной службой RDP (десктопные версии Windows также поддерживают несколько одновременных rdp подключений).
The client has initiated a multi-transport connection to the server 192.168.31.102.
Следующий RDP скрипт выведет историю RDP подключений на указанном компьютере (для получения событий Event Log используется командлет Get-WinEvent):
$properties = @(
@{n='TimeStamp';e={$_.TimeCreated}}
@{n='LocalUser';e={$_.UserID}}
@{n='Target RDP host';e={$_.Properties[1].Value}}
)
Get-WinEvent -FilterHashTable @{LogName='Microsoft-Windows-TerminalServices-RDPClient/Operational';ID='1102'} | Select-Object $properties
Скрипт возвращает SID пользователей, которые инициировали RDP подключения на этом компьютере и DNS имена/IP адреса серверов, к которым подключались пользователи. Вы можете преобразовать SID в имена пользователей.
Также история RDP подключений пользователя хранится в реестре.
In this article, we’ll describe how to get and audit the RDP connection logs in Windows. The RDP connection logs allow RDS terminal server administrators to get information about which users logged on to the server when a specific RDP user logged on and ended up the session, and from which device (DNS name or IP address) the user logged on.
Contents:
- RDP Connection Events in Windows Event Viewer
- Getting Remote Desktop Login History with PowerShell
- Outgoing RDP Connection Logs in Windows
The article is applicable when analyzing RDP logs for both Windows Server 2022/2019/2016 and desktop editions (Windows 11 and 10).
RDP Connection Events in Windows Event Viewer
When a user connects to a Remote Desktop-enabled or RDS host, information about these events is stored in the Event Viewer logs (eventvwr.msc
). Consider the main stages of RDP connection and related events in the Event Viewer, which may be of interest to the administrator
- Network Connection;
- Authentication;
- Logon;
- Session Disconnect/Reconnect;
- Logoff.
Network Connection – establishing a network connection to a server from the user’s RDP client. It is the event with the EventID 1149 (Remote Desktop Services: User authentication succeeded
). If this event is found, it doesn’t mean that user authentication has been successful. This log is located in “Applications and Services Logs -> Microsoft -> Windows -> Terminal-Services-RemoteConnectionManager > Operational”. Enable the log filter for this event (right-click the log -> Filter Current Log -> EventId 1149).
You can list all RDP connection attempts with PowerShell:
$RDPAuths = Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational' -FilterXPath '<QueryList><Query Id="0"><Select>*[System[EventID=1149]]</Select></Query></QueryList>'
[xml[]]$xml=$RDPAuths|Foreach{$_.ToXml()}
$EventData = Foreach ($event in $xml.Event)
{ New-Object PSObject -Property @{
TimeCreated = (Get-Date ($event.System.TimeCreated.SystemTime) -Format 'yyyy-MM-dd hh:mm:ss K')
User = $event.UserData.EventXML.Param1
Domain = $event.UserData.EventXML.Param2
Client = $event.UserData.EventXML.Param3
}
} $EventData | FT
Then you will get an event list with the history of all RDP connections to this server. The logs provide a username, a domain (in this case the Network Level Authentication is used; if NLA is disabled, the event description looks differently), and the IP address of the user’s computer.
Authentication shows whether an RDP user has been successfully authenticated on the server or not. The log is located under Windows -> Security. So, you may be interested in the events with the EventID 4624 (An account was successfully logged on
) or 4625 (An account failed to log on
).
Please, pay attention to the LogonType value in the event description.
- LogonType = 10 or 3 — if the Remote Desktop service has been used to create a new session during log on;
- LogonType = 7, means that a user has reconnected to the existing RDP session;
- LogonType = 5 – RDP connection to the server console (in the mstsc.exe /admin mode).
In this case, the user name is contained in the event description in the Account Name field, the computer name in the Workstation Name, and the user IP in the Source Network Address.
Please, note the value of the LogonID field. This is a unique user RDP session identifier that helps track the user’s further activity. However, if an RDP session is disconnected and a user reconnects to it, the user will be assigned a new LogonID (although the RDP session remains the same).
You can get a list of successful RDP authentication events (EventID 4624) using this PowerShell command:
Get-EventLog security -after (Get-date -hour 0 -minute 0 -second 0) | ?{$_.eventid -eq 4624 -and $_.Message -match 'logon type:\s+(10)\s'} | Out-GridView
Logon refers to an RDP login to Windows. EventID 21 – this event appears after a user has been successfully authenticated (Remote Desktop Services: Session logon succeeded
). These events are located in the “Applications and Services Logs -> Microsoft -> Windows -> TerminalServices-LocalSessionManager -> Operational”. As you can see, here you can find the ID of a user RDP session — Session ID.
EventID – 21 (Remote Desktop Services: Shell start notification received
) indicates that the Explorer shell has been successfully started (the Windows desktop appears in the user’s RDP session).
Session Disconnect/Reconnect – session disconnection and reconnection events have different IDs depending on what caused the user disconnection (disconnection due to inactivity set in timeouts for RDP sessions, Disconnect option has been selected by the user in the session, RDP session ended by another user or an administrator, etc.). You can find these events in the Event Viewer under “Applications and Services Logs -> Microsoft -> Windows -> TerminalServices-LocalSessionManager -> Operational”. Let’s consider the RDP Event IDs that might be useful:
- EventID – 24 (
Remote Desktop Services: Session has been disconnected
) –a user has disconnected from the RDP session; - EventID – 25 (
Remote Desktop Services: Session reconnection succeeded
) – a user has reconnected to the existing RDP session on the server; - EventID – 39 (
Session <A> has been disconnected by session <B>
) – a user has disconnected from the RDP session by selecting the corresponding menu option (instead of just closing the RDP client window). If the session IDs are different, a user has been disconnected by another user (or administrator); - EventID – 40 (
Session <A> has been disconnected, reason code <B>
). Here you must check the disconnection reason code in the event description. For example:- reason code 0 (
No additional information is available
) means that a user has just closed the RDP client window; - reason code 5 (
The client’s connection was replaced by another connection
) means that a user has reconnected to the previous RDP session; - reason code 11 (
User activity has initiated the disconnect
) a user has clicked the Disconnect button in the start menu.
- reason code 0 (
EventID 4778 in Windows -> Security log (A session was reconnected to a Window Station). A user has reconnected to an RDP session (a user is assigned a new LogonID).
EventID 4779 in “Windows -> Security” log (A session was disconnected from a Window Station
). A user has been disconnected from an RDP session.
Logoff refers to the end of a user session. It is logged as the event with the EventID 23 (Remote Desktop Services: Session logoff succeeded
) under “Applications and Services Logs -> Microsoft -> Windows -> TerminalServices-LocalSessionManager -> Operational”.
At the same time the EventID 4634 (An account was logged off
) appears in the Security log.
The EventID 9009 (The Desktop Window Manager has exited with code <X>
) in the System log means that a user has initiated logoff from the RDP session with both the window and the graphic shell of the user have been terminated.
EventID 4647 — User-initiated logoff
Getting Remote Desktop Login History with PowerShell
Here is a short PowerShell script that lists the history of all RDP connections for the current day from the terminal RDS server event logs. The resulting table shows the connection time, the client’s IP address (DNS computername), and the remote user name (if necessary, you can include other LogonTypes in the report).
Get-EventLog -LogName Security -after (Get-date -hour 0 -minute 0 -second 0)| ?{(4624,4778) -contains $_.EventID -and $_.Message -match 'logon type:\s+(10)\s'}| %{
(new-object -Type PSObject -Property @{
TimeGenerated = $_.TimeGenerated
ClientIP = $_.Message -replace '(?smi).*Source Network Address:\s+([^\s]+)\s+.*','$1'
UserName = $_.Message -replace '(?smi).*\s\sAccount Name:\s+([^\s]+)\s+.*','$1'
UserDomain = $_.Message -replace '(?smi).*\s\sAccount Domain:\s+([^\s]+)\s+.*','$1'
LogonType = $_.Message -replace '(?smi).*Logon Type:\s+([^\s]+)\s+.*','$1'
})
} | sort TimeGenerated -Descending | Select TimeGenerated, ClientIP `
, @{N='Username';E={'{0}\{1}' -f $_.UserDomain,$_.UserName}} `
, @{N='LogType';E={
switch ($_.LogonType) {
2 {'Interactive - local logon'}
3 {'Network connection to shared folder)'}
4 {'Batch'}
5 {'Service'}
7 {'Unlock (after screensaver)'}
8 {'NetworkCleartext'}
9 {'NewCredentials (local impersonation process under existing connection)'}
10 {'RDP'}
11 {'CachedInteractive'}
default {"LogType Not Recognised: $($_.LogonType)"}
}
}}
This method allows you to collect and parse RDP connection logs on a standalone RDSH server. If you have multiple servers in the RDS farm, you can query each of them with this script, or get logs from a management server with the Remote Desktop Connection Broker role.
You can export RDP connection logs from the Event Viewer to a CSV file (for further analysis in an Excel spreadsheet). You can export the log from the Event Viewer GUI (assuming Event Viewer logs are not cleared) or via the command prompt:
WEVTUtil query-events Security > c:\ps\rdp_security_log.txt
Or with PowerShell:
get-winevent -logname "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" | Export-Csv c:\ps\rdp_connection_log.txt -Encoding UTF8
If your users connect to corporate RDS hosts through the Remote Desktop Gateway, you can check the user connection logs in the Microsoft-Windows-TerminalServices-Gateway log by the EventID 302. For example, the following PowerShell script will display the specified user’s connection history through RD Gateway:
$rdpusername="b.smith"
$properties = @(
@{n='User';e={$_.Properties[0].Value}},
@{n='Source IP Adress';e={$_.Properties[1].Value}},
@{n='TimeStamp';e={$_.TimeCreated}}
@{n='Target RDP host';e={$_.Properties[3].Value}}
)
(Get-WinEvent -FilterHashTable @{LogName='Microsoft-Windows-TerminalServices-Gateway/Operational';ID='302'} | Select-Object $properties) -match $rdpusername
You can check the following RD Gateway user connection events in the Microsoft-Windows-TerminalServices-Gateway event log:
- 300 — The user NAME, on client computer DEVICE, met resource authorization policy requirements and was therefore authorized to connect to resource RDPHOST;
- 302 — The user NAME, on client computer DEVICE, connected to resource RDPHOST;
- 303 — The user NAME, on the client computer DEVICE, disconnected from the following network resource: RDPHOST. Before the user disconnected, the client transferred X bytes and received X bytes. The client session duration was X seconds.
You can display the list of current remote sessions on your RDS host with the command:
qwinsta
The command returns the session ID, the USERNAME, and the session state (Active/Disconnect). This command is useful when you need to get the user’s RDP session ID when using shadow Remote Desktop connections.
You can display the list of the running processes in the specific RDP session (the session ID is specified):
qprocess /id:5
Outgoing RDP Connection Logs in Windows
You can also view outgoing RDP connection logs on the client side. They are available in the following event log: Application and Services Logs -> Microsoft -> Windows -> TerminalServices-ClientActiveXCore -> Microsoft-Windows-TerminalServices-RDPClient -> Operational.
For example, EventID 1102 occurs when a user connects to a remote Windows Server RDS host or a Windows 10/11 computer with RDP enabled (desktop Windows editions also support multiple simultaneous RDP connections).
The client has initiated a multi-transport connection to the server 192.168.13.201.
The following RDP script will display the history of RDP client connections on the current computer:
$properties = @(
@{n='TimeStamp';e={$_.TimeCreated}}
@{n='LocalUser';e={$_.UserID}}
@{n='Target RDP host';e={$_.Properties[1].Value}}
)
Get-WinEvent -FilterHashTable @{LogName='Microsoft-Windows-TerminalServices-RDPClient/Operational';ID='1102'} | Select-Object $properties
The script returns the SIDs of the users who initiated RDP connections on this computer, as well as the DNS names/IP addresses of the Remote Desktop hosts that the users connected to. You can convert SIDs to usernames as follows.