Showing posts with label Domain controller. Show all posts
Showing posts with label Domain controller. Show all posts

Monday, March 30, 2015

Group Policy Fails to Apply on Domain Controllers With IPv6 disabled

Forward

Let me start by saying, don't disable IPv6 on domain controllers. There's no reason for it, and it will cause you more headaches in the long run. From what I've read, it used to be best practices in the early days of IPv6, but Windows is smart enough now that it shouldn't have any problems with it.

So I inherited a domain setup where the domain controllers (Running Server 2008 (not R2)) had IPv6 disabled for some reason. It's not well documented why this was done, and it's on my list of things to fix, but for the moment I'm stuck with it.

As to why I'm still running DCs on 2008, shut up it's on my to-do list.

Solution

Disabled 6to4 adapter. 6to4 adapter will register itself in DNS and cause lookup problems. I couldn't find a good way to tell the adapter not to register itself, so I settled for disabling it. From an admin command prompt:
netsh int ipv6 6to4 set state disabled
been running this way for a week or so, and haven't had any more problems. I am able to run a gpupdate on the domain controllers and have it apply successfully.

Problem & Full Story

 See "Forward" as to why I am operating DCs with IPv6 disabled.

Started running into this problem a while back, but had never had the time to troubleshoot it fully. Domain Controllers would randomly stop working correctly requiring reboots and extensive testing. These problems would take the form of

  • Slow logins -- stuck at applying user settings
  • Slow boot -- stuck applying computer settings
  • "no trust relationship" errors
  • DCs failing to apply group policy updates via "gpupdate /force"
    • Updates would apply correctly on reboot
Eventually, going through logs, I was able to narrow it down to a DNS issue. Mostly there were "RPC Server Unavailable" Errors which indicated a lookup failure. The DCs also function as DNS servers, so the fact they had lookup problems when nothing else seemed to was double strange.

Parsing through the "Forward Lookup Zones" I found that the DCs were still registering IPv6 addresses. If I cleared those addresses out manually then everything seemed to work. The DNS entries I cleared out looked like this:

Name                    Type                    Data                    Timestamp
(same as parent folder) IPv6 Host(AAAA)         2222::etc::2220         2/2/22
(same as parent folder) IPv6 Host(AAAA)         2222::etc::2221         2/2/22
...
DC1                     IPv6 Host(AAAA)         2222::etc::2222         2/2/22
DC2                     IPv6 Host(AAAA)         2222::etc::2223         2/2/22

After clearing these out everything would work for awhile. But the entries would eventual re-create themselves and the problems would come back. The (same as parent folder) -- which is a reference to the resolution of mydomain.com -- would recreate every hour or so, whereas the DC1,DC2 entries seemed to only come back on a reboot. It was baffling because the IPv6 adapters were totally disabled, so I couldn't figure out why/how they were continuing to register themselves.

After looking through ways to more forcibly disable IPv6 (through registry hacks, etc.), and deciding that was a bad idea, I thought to look more closely at the addresses that were being registered.  Issuing a ipconfig /all, I realized that those addresses were associated with the 6to4 adapters, not the actual ipv6 interface.

A quick google later to find out how to disable the 6to4 adapter and everything was in order. As mentioned above it's been a week and I haven't seen any side effects to disabling the 6to4 adapter.

Long-term solution is to reenable IPv6 on the domain controllers, but it's been disabled for so long, and since I have no idea why it was disabled in the first place, that will require more careful testing.

Friday, February 28, 2014

Adventures in Powershell: User account locked out continuously

One problem we run into from time to time is when a user's account keeps getting locked out without any obvious reason (They're not typing in the password wrong - though this is probably the number 1 cause). Usually this is the result of some saved credentials somewhere that are no longer valid; They've expired, or there was a password change, or something. However, if the user logs into multiple machines, or has network resources mapped to a personal device, it can be really hard to tell where the bad login attempts are coming from.

So I wrote a neat little powershell function to help out with this. Bad log on attempts are logged in the domain controllers security logs. However, for various reasons, they can be really hard to find (reasons include username not being in the username field, and domain controller security logs having about a billion events at any given time). This powershell function does a little WMI call to each domain controller you specify and looks for these events so you don't have to.

It's a little messy and slow, but can save a great amount of time whenever these events come up.

I've put in some Get-Help features to which explains how to use it. After you import it run "Get-Help Get-WhyIsThisAccountLocked". Or alternatively just read the first 30 lines or so of the code.


The code:
function Get-WhyIsThisAccountLocked
{
    <#
        .SYNOPSIS
            Querys Domain Conrollers for specific log events looking for failed kerberos authentication.
        .Description
            Method can be used to discover where a specific account is being locked out from. This will return a list of log events related to failed authentications which you can use to further troubleshoot. Because of how these events are formated, it is difficult to select specific information out of them - So this returns the whole event. The important fields to look for are 
            AccountName: (verify it returned the correct user - for various reasons it only does a 'like' comparision here)
            Client Address: (Where the bad requests are coming from - note you will probably see some coming from the domain controller(s) - unless the user is acutally tying to log into/acess the domain controller, you can ignore these.)
            Failure Code: (Tells you more about what sort of authentication was being attempted - google "kerberos autentication failure code")
            Service Name: (Can tell you what service was trying to use the account - krbtgt/domain is typically standard login attempt, if it's something else, google it)
        .PARAMETER UserID
            UserID that is being locked out
        .PARAMETER DomainController
            Domain controller(s) to query for event logs. This may be either a single hostname/IP or a comma seperated list.
        .PARAMETER HoursBack
            Number of hours back to search, default is 1. Using large search periods can exponentially slow down the script.
        .PARAMETER OutFile
            File path to output text to - default is to output to command window
        .PARAMETER YesIAmSure
            If OutFile is specified, does not ask to confirm file write/overwrite. Otherwise does nothing.
        .Example
            Get-WhyIsThisAccountLocked -UserID myuser -DomainController "mydomain1,mydomain2" -HoursBack 2 -OutFile c:\temp\output.txt -YesIAmSure
        .Notes
            Author: Keith Ballou
            Date: Feb 28, 2014


    #>
       [CmdletBinding()] 
       param( 
      [Parameter(Mandatory=$true)][string]$UserID,
      [parameter(Mandatory=$true)][string]$DomainController,
      [Parameter(Mandatory=$false)][int]$HoursBack=1,
      [Parameter(Mandatory=$false)][string]$Outfile,
      [Parameter(Mandatory=$false)][switch]$YesIAmSure
)
       $ListofEvents=""
       $SearchTime=(get-date).addhours(-$HoursBack).touniversaltime().tostring("yyyyMMddHHmmss.000000-000")
       Write-Verbose "Searching between $SearchTime and Current Time"
       $ListofDCs=$DomainController.split(',')

       if ($HoursBack -gt 1)
       {
        write-host "WARNING: Using Larger Serach periods can cause this script to take a very long time" -ForegroundColor "Magenta" -BackgroundColor "Black"
       }

    foreach ($DC in $ListofDCs) 
      {
        write-host "Querying... " $DC
        $Temp=Get-WmiObject -ComputerName $DC -Query "Select * from win32_ntlogevent Where LogFile='Security' AND (Eventcode='4771' OR Eventcode='4769') And Message Like '%$UserID%' AND timegenerated > '$SearchTime'"
        foreach($Entry in $Temp)
        {
            Write-Verbose "Processing Entry" 
            $ListofEvents+="-------------------------------------------------------------------`n"
            $ListofEvents+=$Entry.ComputerName + "`n" 
            $ListofEvents+=$Entry.Message + "`n"            
        }
    }
       
    if($OutFile -ne "")
    {
        write-host "`n`nWarning: About to write to $OutFile - This will overwrite any existing data" -ForegroundColor "Magenta" -BackgroundColor "Black"

        if($YesIAmSure)
            {
                out-file -InputObject $ListofEvents -FilePath $OutFile
            }
        else {
            {
                out-file -InputObject $ListofEvents -FilePath $OutFile -Confirm
            }
        }
    }   

    else {
        write-host $ListofEvents
    }
    

}