How to Programmatically Identify SMB Client Versions Connected to Windows Server 2016 Shares


2 views

When administering a Windows Server 2016 environment, one common pain point is determining which SMB protocol versions your connected clients are using. While Get-SmbConnection shows outgoing connections, we need a different approach for inbound client connections.

Here are three reliable techniques to identify client SMB versions:

1. PowerShell with WMI:

Get-WmiObject -Class MSFT_SmbSession -Namespace Root\Microsoft\Windows\SMBServer | 
Select-Object ClientComputerName, Dialect

2. Using Performance Counters:

Get-Counter -Counter "\SMB Server Sessions(*)\Dialect" | 
Select-Object -ExpandProperty CounterSamples | 
Where-Object {$_.CookedValue -ne 0} | 
Format-Table -AutoSize

Combine these approaches into a reusable script:

function Get-SmbClientVersions {
    $sessions = Get-SmbSession
    $results = @()
    
    foreach ($session in $sessions) {
        $clientInfo = [PSCustomObject]@{
            ClientIP = $session.ClientComputerName
            Username = $session.UserName
            SMBVersion = switch ($session.Dialect) {
                "2.002" { "SMB 2.0" }
                "2.???" { "SMB 2.1" }
                "3.000" { "SMB 3.0" }
                "3.002" { "SMB 3.1.1" }
                default { "Unknown ($_)" }
            }
            SessionId = $session.SessionId
        }
        $results += $clientInfo
    }
    
    return $results
}

The dialect strings correspond to specific SMB versions:

  • 2.002 = SMB 2.0 (Windows Vista/Server 2008)
  • 2.??? = SMB 2.1 (Windows 7/Server 2008 R2)
  • 3.000 = SMB 3.0 (Windows 8/Server 2012)
  • 3.002 = SMB 3.1.1 (Windows 10/Server 2016)

For continuous monitoring, configure SMB auditing:

# Enable SMB auditing
Set-SmbServerConfiguration -AuditSmb1Access $true -Force
Set-SmbServerConfiguration -AuditSmb2Access $true -Force

# Query SMB connection events
Get-WinEvent -LogName "Microsoft-Windows-SmbClient/Security" | 
Where-Object {$_.Id -eq 30800} | 
Select-Object TimeCreated, Message

If you're not seeing expected results:

  1. Verify the SMB server service is running
  2. Check firewall settings (TCP 445 must be open)
  3. Ensure proper permissions (requires admin rights)
  4. Confirm clients are actually connected to shares

When administering a Windows Server 2016 environment, you might need to audit which SMB protocol versions (SMBv1, SMBv2, or SMBv3) your connected clients are using. While Get-SmbConnection shows outgoing connections from the server, we need different techniques to monitor incoming client connections.

This approach taps into Windows Management Instrumentation to reveal active SMB sessions:

# Get all active SMB sessions with protocol version
Get-WmiObject -Class Win32_ServerSession -ComputerName $env:COMPUTERNAME | 
Where-Object { $_.Active } | 
Select-Object UserName, ClientComputerName, 
    @{Name="SMBVersion";Expression={
        switch ($_.ProtocolType) {
            0 { "SMB1" }
            1 { "SMB2" }
            2 { "SMB3" }
            default { "Unknown" }
        }
    }}

Windows Server logs SMB connection details in the Microsoft-Windows-SMBServer/Operational log:

# Query SMB server operational logs
Get-WinEvent -LogName "Microsoft-Windows-SMBServer/Operational" -MaxEvents 100 | 
Where-Object { $_.Id -eq 3080 } | 
Select-Object TimeCreated, 
    @{Name="ClientIP";Expression={ $_.Properties[0].Value }},
    @{Name="SMBVersion";Expression={
        $dialect = $_.Properties[4].Value
        if ($dialect -like "*2.1*") { "SMB3" }
        elseif ($dialect -like "*2.0*") { "SMB2" }
        else { "SMB1" }
    }}

SMB Server performance counters can reveal protocol version usage patterns:

# Check SMB protocol distribution
Get-Counter -Counter "\SMB Server Sessions(*)\Dialect" | 
Select-Object -ExpandProperty CounterSamples | 
Where-Object { $_.InstanceName -notlike "*_Total*" } | 
Select-Object InstanceName, CookedValue

Combine these methods into a persistent monitoring solution:

# Persistent SMB version monitor
$query = @"
<QueryList>
  <Query Id="0" Path="Microsoft-Windows-SMBServer/Operational">
    <Select Path="Microsoft-Windows-SMBServer/Operational">
      *[System[Provider[@Name='Microsoft-Windows-SMBServer'] and (EventID=3080)]]
    </Select>
  </Query>
</QueryList>
"@

Register-WinEvent -Query $query -Action {
    param($event)
    $clientIP = $event.Properties[0].Value
    $dialect = $event.Properties[4].Value
    
    $version = switch -Wildcard ($dialect) {
        "*2.1*" { "SMB3" }
        "*2.0*" { "SMB2" }
        default { "SMB1" }
    }
    
    Write-Host "$(Get-Date -Format 'HH:mm:ss') - $clientIP connected via $version ($dialect)"
}