Windows OS Hub
  • Windows Server
    • Windows Server 2022
    • Windows Server 2019
    • Windows Server 2016
    • Windows Server 2012 R2
    • Windows Server 2008 R2
    • SCCM
  • Active Directory
    • Active Directory Domain Services (AD DS)
    • Group Policies
  • Windows Clients
    • Windows 11
    • Windows 10
    • Windows 8
    • Windows 7
    • Windows XP
    • MS Office
    • Outlook
  • Virtualization
    • VMWare
    • Hyper-V
    • KVM
  • PowerShell
  • Exchange
  • Cloud
    • Azure
    • Microsoft 365
    • Office 365
  • Linux
    • CentOS
    • RHEL
    • Ubuntu
  • Home
  • About

Windows OS Hub

  • Windows Server
    • Windows Server 2022
    • Windows Server 2019
    • Windows Server 2016
    • Windows Server 2012 R2
    • Windows Server 2008 R2
    • SCCM
  • Active Directory
    • Active Directory Domain Services (AD DS)
    • Group Policies
  • Windows Clients
    • Windows 11
    • Windows 10
    • Windows 8
    • Windows 7
    • Windows XP
    • MS Office
    • Outlook
  • Virtualization
    • VMWare
    • Hyper-V
    • KVM
  • PowerShell
  • Exchange
  • Cloud
    • Azure
    • Microsoft 365
    • Office 365
  • Linux
    • CentOS
    • RHEL
    • Ubuntu

 Windows OS Hub / Windows Server 2019 / Tracking and Analyzing Remote Desktop Connection Logs in Windows

February 20, 2023 PowerShellWindows Server 2016Windows Server 2019

Tracking and Analyzing Remote Desktop Connection Logs in Windows

In this article, we’ll describe how to get and audit the RDP connection logs in Windows. The RDP connection logs allow RDS terminal servers 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/2012R2 and to desktop editions (Windows 11, 10, and 8.1).

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

  1. Network Connection;
  2. Authentication;
  3. Logon;
  4. Session Disconnect/Reconnect;
  5. 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).

windows event log Terminal-Services-RemoteConnectionManager filtering

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

powershell script: get rdp conneciton events

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.

EventID 1149 - Remote Desktop Services: User authentication succeeded

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).
You can use RDP authentication failure events to protect against RDP brute force attacks. You can automatically block attacker IPs at the Windows Defender Firewall using a simple PowerShell script.

security log: rdp logon event with the username and ip adress of the remote client

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

list sucess rdp auth event with an EventID 4624

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). This 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: Session logon succeeded

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.

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”.

EventID 23 - Remote Desktop Services: Session logoff succeeded

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)"}
}
}}

powershell: list todays rdp logons with an ip and username

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

rd gateway user connection logs

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 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.

Qwinsta - list RDP sessions and usernames

You can display the list of the running processes in the specific RDP session (the session ID is specified):

qprocess /id:5

qprocess - get process list for an RDP session

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.

Microsoft-Windows-TerminalServices-RDPClient connection event in Windows

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

rdp client connection events

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.

Also, you can check the RDP connection history in the user’s registry.

25 comments
8
Facebook Twitter Google + Pinterest
previous post
Windows Subsystem for Android: Running Android Apps on Windows 11
next post
Configuring RDS Connection Broker High Availability on Windows Server

Related Reading

How to Connect VPN Before Windows Logon

November 14, 2023

Using WPAD (Web Proxy Auto-Discovery Protocol) on Windows

November 7, 2023

Send Emails with Microsoft Graph API and PowerShell

November 6, 2023

Zabbix: How to Get Data from PowerShell Scripts

October 27, 2023

Tracking Printer Usage with Windows Event Viewer Logs

October 19, 2023

25 comments

Roman November 6, 2019 - 3:14 pm

First at all great article, it helped me already with some analysis.

But i would have a short question about an reason code i receive in the TerminalServices-LocalSessionManager Log, maybe you can help me with it:

“Session 90 has been disconnected, reason code 3489660929”

What is the reason code: 3489660929?

Currently my users are experiencing random disconnects on my RDS 2019 Farm where always this reason code pops up.

Reply
Stephen Price June 23, 2020 - 3:43 pm

I am trying to run this on a Windows 10 machine and nothing occurs. I am running from the ISE under admin privileges. Still get no response, just returns to prompt.

Reply
Jan Čížek July 31, 2020 - 9:05 am

And are there some connections to this machine via RDP ? If not, then the log is empty.

Reply
Fionn August 13, 2020 - 7:37 am

top info 🙂 thanks a lot!

Reply
Sam October 7, 2020 - 12:20 am

great article and very detailed information.
my question, though, can you do this (powershell scripts) of another computer? like remotely?

Reply
CCPCh December 17, 2020 - 6:24 pm

Useful, Thank you.

Reply
arman January 25, 2021 - 4:02 pm

Great article and very helpful, thank you
I am running it in windows 2016 and return all value fine but for user name is showing like -\-
any idea?

Reply
Francisco February 3, 2021 - 6:55 pm

Hi. Very good job, it worked awesomely to me.

How can I set the Event Log properties for the Applications and Services Logs.

For windows logs I use “Limit-EventLog -logname …..”, but I can’t figure out how to point to that session.

Reply
Chip February 5, 2021 - 2:47 pm

Thanks for sharing. Very detailed. However, I’m having same issue as Arman. When running PowerShell script on Windows Server 2019, Username results display: “\-” (without quotes).

Reply
anon May 25, 2021 - 1:06 pm

If you are getting the “-\-” problem with Domain and username

replace

UserName = $_.Message -replace ‘(?smi).*Account Name:\s+([^\s]+)\s+.*’,’$1′
UserDomain = $_.Message -replace ‘(?smi).*Account Domain:\s+([^\s]+)\s+.*’,’$1′

with

UserName = $_.Message -replace ‘(?smi).*\s\sAccount Name:\s+([^\s]+)\s+.*’,’$1′
UserDomain = $_.Message -replace ‘(?smi).*\s\sAccount Domain:\s+([^\s]+)\s+.*’,’$1′

The regex was picking up the “Network Account name” and “Network Account Domain” entries in error

Reply
f4d0 June 23, 2021 - 9:15 am

The article is great. Thanks for sharing.
But sometimes there are no 4624 event logs because of the rotation of the logs, in fact most of the times if we think from a DFIR consulting perspective.
What do you propose on this cases?

Reply
Roger Palasi Masip October 30, 2021 - 10:30 am

This worked like a charm, thank you

Reply
Jan Bartoš December 1, 2021 - 7:56 am

Guys, how do I limit the export for just 1 user I am looking for? Thank you for the script, it works great.

Reply
frank alvrec December 13, 2021 - 5:51 am

Not working on windows server 2019 🙁

Any idea?

Reply
L1ttl3J1m January 19, 2022 - 8:11 am

Brilliant article, very helpful, I refer to it regularly.

Just one last line you could add, though, about the next step down where a connection doesn’t even get to the Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational log…

Reply
salih February 13, 2022 - 7:30 pm

thanks for valuable article. it enlightened me about rdp logs location.

Reply
Gilbert March 8, 2022 - 8:54 pm

Very informative…however…I have a unique issue: I am looking for an attempt to do a RDP from the server (X) to an unknown IP address (Computer Y).
I am not able to view any event/logs/activity indicating a RDP task was initiated. I do see it in the Firewall log that RDP is blocked – whereas Server (x) was the source and Computer (Y) is the designation. I am not able to find rhyme or reason for RDP is being initiated.

Reply
admin March 9, 2022 - 11:39 am

Check RDP client events. Look under ‘Application and Services Logs’ -> ‘Microsoft’ -> ‘Windows’ -> ‘TerminalServices-ClientActiveXCore’ -> ‘Microsoft-Windows-TerminalServices-RDPClient/Operation’

Reply
Irish June 21, 2022 - 1:35 pm

I’ve got a very simple question:
Been bashing my head against this for hours now, but how do you modify the timeframe of the PS script from only the current day to say, the current month or so?

Reply
admin July 14, 2022 - 8:51 am

Last 30 days:
(get-date).AddMonths(-1)
Current month:
$LastMonth = (Get-Date).AddMonths(-1)
$FirstDayOfMonth = $LastMonth | Get-Date -Format "yyyy/MM/01"
Get-EventLog security -after $FirstDayOfMonth .....

Reply
Andre April 6, 2023 - 6:27 pm

Can you send me your contact?

Reply
hakim July 21, 2023 - 4:22 pm

What can we do if we do not have an RDS server and we want to log all domain users through AD? I hope I could explain myself, I used translate. thanks

Reply
Michael July 26, 2023 - 2:09 pm

Thank you for the great article!

One note: this – “LogonType = 10 or 3 — if the Remote Desktop service has been used to create a new session during log on;” is not correct: only LogonType=10 designates RDP logon, LogonType=3 means any network logon (accessing a shared folder, for example) so filtering the Security log on logontype=3 will be useless in terms of RDP.

Reply
Charles October 5, 2023 - 11:52 pm

Hi mate,

Firstly, thanks for this article… very helpful.

I’m trying to find a way to send notifications to a Microsoft Teams channel every time someone logs on/logs off into/from a server.

I know how to do the Power Automate flow to get triggered by an API request that could be done using Powershell using Invoke-WebRequest.

But doing the trigger on the server side is hard. I’m thinking of something like a Task Schedule job that is triggered by those specific Event IDs, but hasn’t worked for me so far.

Any other ideas? Have you done any article on that?

Thanks a lot!

Reply
admin October 6, 2023 - 10:22 am

You can send a notification to your Teams channel from PowerShell as follow
Then attach this PowerShell script to the required event IDs (see an example here)

Reply

Leave a Comment Cancel Reply

Categories

  • Active Directory
  • Group Policies
  • Exchange Server
  • Microsoft 365
  • Azure
  • Windows 11
  • Windows 10
  • Windows Server 2022
  • Windows Server 2019
  • Windows Server 2016
  • PowerShell
  • VMWare
  • Hyper-V
  • Linux
  • MS Office

Recent Posts

  • How to Connect VPN Before Windows Logon

    November 14, 2023
  • Removing Azure Arc Setup Feature on Windows Server 2022

    November 9, 2023
  • Using WPAD (Web Proxy Auto-Discovery Protocol) on Windows

    November 7, 2023
  • Send Emails with Microsoft Graph API and PowerShell

    November 6, 2023
  • Zabbix: How to Get Data from PowerShell Scripts

    October 27, 2023
  • Tracking Printer Usage with Windows Event Viewer Logs

    October 19, 2023
  • PowerShell: Configure Certificate-Based Authentication for Exchange Online (Azure)

    October 15, 2023
  • Reset Root Password in VMware ESXi

    October 12, 2023
  • How to Query and Change Teams User Presence Status with PowerShell

    October 8, 2023
  • How to Increase Size of Disk Partition in Ubuntu

    October 5, 2023

Follow us

  • Facebook
  • Twitter
  • Telegram
Popular Posts
  • Fix: Remote Desktop Licensing Mode is not Configured
  • Manage Windows Updates with PSWindowsUpdate PowerShell Module
  • Configuring Port Forwarding in Windows
  • Start Menu or Taskbar Search Not Working in Windows 10/11
  • How to Install Remote Server Administration Tools (RSAT) on Windows
  • How to Delete Old User Profiles in Windows
  • Get-ADUser: Find Active Directory User Info with PowerShell
Footer Logo

@2014 - 2023 - Windows OS Hub. All about operating systems for sysadmins


Back To Top