To get the IP addresses of the remote desktop sessions behind a Remote Desktop Gateway, you need to open RD Gateway Manager, go to Monitoring section and check each of the connected sessions to find their IP addresses. If you want to look further for their geolocations as well, you
That is just too many steps involved and there got to be a better way to handle this if I want to monitor all incoming remote sessions on a regular consistent basis. Time to ask PowerShell for help.
You can use
Get-WmiObject -class "Win32_TSGatewayConnection" -namespace "root\cimv2\TerminalServices" -ComputerName remote_server -Authentication 6
To get the geolocation info, you can call up Invoke-RestMethod cmdlet that deals with HTTP/HTTPs requests related to Representational State Transfer (REST) web services that return richly structured data, such as XML or JSON. It’s a perfect candidate to perform the call and display the result in a nicely formatted way. It runs something like this:
Invoke-RestMethod -Uri "http://ipinfo.io/$ipaddress"
For more information about getting Geolocation info from PowerShell, check out this post.
Putting together, here is the code you can use to get all live sessions’ IP addresses and their geolocation info on the Remote Gateway server.
$ts = Get-WmiObject -class "Win32_TSGatewayConnection" -namespace "root\cimv2\TerminalServices" -ComputerName remote_server -Authentication 6
$ofs = "`r`n`r`n"
$body = "Gateway connections: " + $ofs
foreach ($connection in $ts)
{
$username = $connection.username
$ip = $connection.clientaddress
$geo = Invoke-RestMethod -Uri "http://ipinfo.io/$ip"
$body = $body + $connection.ConnectedTime + $username + $geo + $ofs
}
$body
It works great to get data from the live sessions. What about the closed sessions that you missed? You can create a scheduled task that triggers a PowerShell script every time a session goes live. The trigger needs to be based on the event, more specifically, Microsoft-Windows-TerminalServices-Gateway/Operational. See the trigger below:
The script will then collect the IP info of that session and save it to the event log.
$ts = Get-WmiObject -class "Win32_TSGatewayConnection" -namespace "root\cimv2\TerminalServices" -ComputerName Remote_Server -Authentication 6 | Sort-Object ConnectionDuration -Desc
$ofs = "`r`n`r`n"
$body = "Gateway connections: " + $ofs
foreach ($connection in $ts)
{
$username = $connection.username
$ip = $connection.clientaddress
$geo = Invoke-RestMethod -Uri "http://ipinfo.io/$ip"
}
$body = $body + $connection.ConnectedTime + ": " +$username + $geo + $ofs
$server = "remote_server"
$logname = "application"
#New-EventLog -ComputerName $server -Logname $logname -Source "MyApp"
Write-EventLog -ComputerName $server -Logname $logname -Source "MyApp" -EventID 3001 -Message $body
Note that the script only extracts the last session from the session collection so only the newest info will be saved into the log. Once the data is saved in the event log, I can run another PowerShell script to collect and send them to me via email. And I can schedule that script to run on
Hi Kent,
How can you create the mentioned scheduled task that triggers a PowerShell script every time a session goes live? What event id should be monitored for this?
Thank you and best regards,
Roland
I’ve updated the post with a screenshot of the trigger setting. Hope it helps.
Hi Kent,
I am running this both manually and as a task.
It only seems to capture the last record, rather than looping through each connection, writing to log and then doing the next one.
Am I missing something ?
$ts should return several “$connection” users to record
Hi Kent,
I’ve implemented the task scheduler script and it seems to work, but doesn’t seem to trigger as often as it should. Should it be running on the gateway server? Or on each RDS server?
As far as i can tell. With the task scheduler on the gateway running the script it only triggers whenever I logon directly to the gateway.