How to Query Kerberos Key Version (KVNO) from Active Directory for Troubleshooting Linux-Windows KDC Authentication Issues


2 views

When debugging Kerberos authentication between Linux clients and Windows KDC (Key Distribution Center), the Key Version Number (KVNO) becomes critical. Each time a Kerberos principal's password changes, the KVNO increments, and mismatched versions can cause authentication failures without clear error messages.

The most efficient way to retrieve KVNO from Active Directory is using PowerShell with the Active Directory module:


Import-Module ActiveDirectory
Get-ADObject -Filter "servicePrincipalName -eq 'HTTP/yourhost.yourdomain.com'" -Properties * | 
Select-Object msDS-KeyVersionNumber, servicePrincipalName

For a specific user account:


Get-ADUser username -Properties msDS-KeyVersionNumber | 
Select-Object SamAccountName, msDS-KeyVersionNumber

For environments where PowerShell isn't available, use this LDAP query:


ldapsearch -x -H ldap://yourdc.yourdomain.com -D "CN=admin,CN=Users,DC=yourdomain,DC=com" -w password -b "DC=yourdomain,DC=com" "(&(objectClass=user)(servicePrincipalName=HTTP/yourhost.yourdomain.com))" msDS-KeyVersionNumber

The returned msDS-KeyVersionNumber represents the current key version. Compare this with:

  • The Linux client's keytab file (check with klist -kte)
  • Event Viewer logs on the KDC (Event ID 4769)

If you identify a version mismatch but can't reset the SPN:

  1. On Linux: kinit -k -t /etc/krb5.keytab HTTP/yourhost.yourdomain.com
  2. Check ticket with: klist
  3. Verify KDC logs for encryption type negotiation errors

For comprehensive troubleshooting, retrieve all cryptographic attributes:


Get-ADObject -Filter "servicePrincipalName -eq 'HTTP/yourhost.yourdomain.com'" -Properties msDS-KeyVersionNumber,msDS-SupportedEncryptionTypes,userAccountControl | 
Select-Object servicePrincipalName,msDS-KeyVersionNumber,msDS-SupportedEncryptionTypes,userAccountControl


When Linux hosts authenticate against Windows Kerberos domains, version mismatches in encryption keys (KVNO - Key Version Number) can cause subtle failures. Instead of blindly recreating service principals, let's explore how to inspect the current KVNO values directly from Active Directory.

The simplest way for Windows admins to check KVNO is through PowerShell's ActiveDirectory module:

Import-Module ActiveDirectory
Get-ADUser -Identity "svc_account" -Properties msDS-KeyVersionNumber | 
    Select-Object Name, msDS-KeyVersionNumber

# For computer accounts:
Get-ADComputer -Identity "server01" -Properties msDS-KeyVersionNumber |
    Select-Object Name, msDS-KeyVersionNumber

For cross-platform environments, an LDAP query gives more flexibility:

# Using ldapsearch on Linux:
ldapsearch -H ldap://dc01.example.com -x -D "CN=admin,DC=example,DC=com" -W \
    -b "DC=example,DC=com" "(sAMAccountName=svc_account)" msDS-KeyVersionNumber

# Using PowerShell without AD module:
$searcher = [DirectoryServices.DirectorySearcher]::new(
    [DirectoryServices.DirectoryEntry]::new("LDAP://DC=example,DC=com")
)
$searcher.Filter = "(sAMAccountName=svc_account)"
$searcher.PropertiesToLoad.Add("msDS-KeyVersionNumber") | Out-Null
$result = $searcher.FindOne()
$result.Properties["msds-keyversionnumber"]

The KVNO represents the encryption key version. When troubleshooting:

  • Compare with klist -ke output on Linux clients
  • Typical rotation scenarios increment KVNO by 1
  • Gaps larger than 1 may indicate manual key resets

To verify keytab contents against AD:

# On Linux:
ktutil
ktutil: read_kt /etc/krb5.keytab
ktutil: list

# Compare the KVNO from keytab with AD value
# If mismatched, use ktpass or similar to regenerate:
ktpass -princ host/server01.example.com@EXAMPLE.COM -mapuser server01$ \
    -crypto ALL -ptype KRB5_NT_PRINCIPAL -pass * -kvno 5 \
    -out server01.keytab

For critical services, consider monitoring KVNO changes:

# PowerShell monitoring script
$lastKVNO = 0
while($true) {
    $current = Get-ADUser "svc_account" -Properties msDS-KeyVersionNumber |
        Select-Object -ExpandProperty msDS-KeyVersionNumber
    if($current -ne $lastKVNO) {
        Write-Host "KVNO changed from $lastKVNO to $current at $(Get-Date)"
        $lastKVNO = $current
    }
    Start-Sleep -Seconds 3600 # Check hourly
}