How to Inspect Active TLS Sessions on Windows 11 from PowerShell
🔍 WiseChecker

How to Inspect Active TLS Sessions on Windows 11 from PowerShell

When you need to verify whether an application or service is using TLS 1.2, TLS 1.3, or an older protocol, inspecting active TLS sessions directly from PowerShell gives you precise control. Windows 11 does not expose live TLS session details in Task Manager or the standard network monitoring tools. The root cause is that the operating system handles encryption at the kernel level through the SChannel security provider, and user-facing tools only show raw TCP connections without protocol version information. This article explains how to use built-in PowerShell cmdlets and .NET classes to list active TLS sessions, identify the negotiated protocol version, and filter results by process or remote address.

Key Takeaways: Inspecting TLS Sessions from PowerShell

  • Get-NetTCPConnection with .NET SslStream: Lists all TCP connections and then checks each for TLS protocol version using the SslStream class.
  • .NET System.Net.Security.SslStream class: Queries the negotiated TLS version on an active socket without interrupting the session.
  • Filtering by process name or remote port: Narrows results to specific applications or services such as web browsers, email clients, or SQL Server.

ADVERTISEMENT

How TLS Sessions Work on Windows 11 and Why Standard Tools Are Insufficient

TLS sessions on Windows 11 are managed by the SChannel security service provider at the kernel level. When an application initiates a TLS handshake, SChannel negotiates the highest mutually supported protocol version and establishes an encrypted session. The TCP connection itself is visible in tools like netstat or Get-NetTCPConnection, but the protocol version TLS 1.2 versus TLS 1.3 is not exposed in those outputs. Task Manager shows network usage per process but does not reveal encryption details. To see the actual TLS version, you must programmatically inspect the socket after the handshake completes. PowerShell can do this by leveraging the .NET SslStream class, which reads the SslProtocols property from an active connection.

Prerequisites for Inspecting TLS Sessions

You need Windows 11 build 22000 or later with PowerShell 5.1 or PowerShell 7. Running the inspection script requires administrative privileges if you want to access sockets owned by other processes. The target application must have an active TLS connection at the time of inspection. The script does not interfere with the connection; it only reads the negotiated protocol from the existing socket.

Using Get-NetTCPConnection and .NET SslStream to List Active TLS Sessions

The following method uses Get-NetTCPConnection to retrieve all TCP connections with the Established state. For each connection, it creates a temporary TCP client object and retrieves the underlying socket. It then calls the .NET SslStream class to authenticate the remote endpoint and reads the SslProtocol property. The script outputs the local address, remote address, process ID, and the negotiated TLS version.

  1. Open PowerShell as Administrator
    Press the Windows key, type PowerShell, right-click Windows PowerShell or PowerShell 7, and select Run as administrator. Click Yes in the User Account Control prompt.
  2. Run the Get-NetTCPConnection cmdlet to list established connections
    In the PowerShell window, type the following command and press Enter: Get-NetTCPConnection -State Established | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, OwningProcess. This shows all active TCP connections with their process IDs. Note the RemoteAddress and RemotePort of the TLS sessions you want to inspect.
  3. Create a PowerShell script to inspect TLS versions
    Open Notepad or any text editor. Paste the following script and save it as Get-TlsSession.ps1 on your desktop. The script takes a remote address and port as parameters and outputs the TLS version for each matching connection.
param(
    [string]$RemoteAddress = "".ToLower(),
    [int]$RemotePort = 443
)

$connections = Get-NetTCPConnection -State Established | Where-Object {
    ($_.RemoteAddress -like $RemoteAddress) -and ($_.RemotePort -eq $RemotePort)
}

foreach ($conn in $connections) {
    $tcpClient = New-Object System.Net.Sockets.TcpClient
    try {
        $tcpClient.Client.DontFragment = $true
        $tcpClient.Client.SetSocketOption([System.Net.Sockets.SocketOptionLevel]::Tcp, [System.Net.Sockets.SocketOptionName]::NoDelay, $true)
        $tcpClient.Client.Connect($conn.RemoteAddress, $conn.RemotePort)
        $sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false, { $true })
        $sslStream.AuthenticateAsClient($conn.RemoteAddress)
        $tlsVersion = $sslStream.SslProtocol.ToString()
        Write-Output "Process ID: $($conn.OwningProcess), Remote: $($conn.RemoteAddress):$($conn.RemotePort), TLS: $tlsVersion"
    }
    catch {
        Write-Output "Process ID: $($conn.OwningProcess), Remote: $($conn.RemoteAddress):$($conn.RemotePort), TLS: Error - $($_.Exception.Message)"
    }
    finally {
        $sslStream.Close()
        $tcpClient.Close()
    }
}
  1. Execute the script to inspect TLS sessions
    In the PowerShell window, navigate to the desktop: cd ~\Desktop. Run the script: .\Get-TlsSession.ps1. To filter by a specific remote address, use .\Get-TlsSession.ps1 -RemoteAddress "microsoft.com". To filter by a non-default port, use .\Get-TlsSession.ps1 -RemotePort 993 for IMAPS.
  2. Interpret the output
    The script prints each connection with the process ID, remote endpoint, and the TLS version string. Possible values include Ssl3, Tls, Tls11, Tls12, Tls13, or an error message if the connection is not TLS. A value of Tls13 indicates TLS 1.3. Tls12 indicates TLS 1.2. Tls11 or Tls indicates older, less secure protocols.

ADVERTISEMENT

Common Issues When Inspecting TLS Sessions and How to Avoid Them

Script returns an error stating the socket is already in use

The script attempts to connect to the same remote endpoint that is already connected. This can fail if the remote server closes the connection during the handshake or if the local firewall blocks outbound connections. To work around this, ensure the remote service is accessible from your machine. You can test connectivity with Test-NetConnection -ComputerName <remote> -Port <port> before running the script.

Script returns TLS: Error with System.UnauthorizedAccessException

This error occurs when PowerShell does not have permission to open a socket owned by another process. Run PowerShell as Administrator to resolve this. If the problem persists, the target connection might be owned by the SYSTEM account or a protected process. In that case, you cannot inspect the TLS session from user mode.

Output shows only error messages for all connections

The script attempts to authenticate as a client to the remote server. If the remote server requires a specific client certificate or uses a non-standard TLS configuration, the authentication fails. This is expected for services that do not accept arbitrary client connections. The script works best with public web servers and standard TLS services.

Get-NetTCPConnection vs SslStream: Capability Comparison

Item Get-NetTCPConnection .NET SslStream Class
Shows TLS protocol version No Yes
Requires admin rights No for own processes Yes for other processes
Disrupts the connection No No, it only reads
Works with all TCP connections Yes Only TLS connections
Outputs process name By process ID By process ID

You can now inspect active TLS sessions on Windows 11 directly from PowerShell without third-party tools. The script uses Get-NetTCPConnection to list connections and the .NET SslStream class to read the negotiated TLS version. For a more permanent monitoring solution, consider scheduling the script with Task Scheduler and logging the output to a CSV file. To go further, modify the script to check the certificate chain by reading the RemoteCertificate property of the SslStream object.

ADVERTISEMENT