Ken St. Cyr's Blog

No snappy subtitle... just technology

Ken St. Cyr's Blog

  • Understanding Urgent Replication

    I've found that a lot of people tend to be confused about the topic of urgent replication and what exactly its supposed to do. One common misconception is that urgent replication ensures that a change is converged through the entire domain immediately. This isn't necessarily true. Let's look at this in more detail...

    Change Notifications

    So how does a DC know that it needs to replicate? Replication is a fairly complex process that I may talk about more in the future, but for now you just need to understand a couple of key concepts. When changes are made, the DC will notify it's replication partners in the same site that it has a change for them. This is called change notification.

    Changes Between Sites

    Changes between DCs in different sites don't use change notifications. Instead, DCs request changes on the interval defined in the site link. But the lowest value we can have for inter-site replication in the site link is 15 minutes. What if we want to converge sooner? Take the below architecture for example.

    img1

    Here we have 4 sites, one connected to another. With a replication interval of 15 minutes in each site link, convergence of a change from site A to site D can take as long as 45 minutes (A to B = 15 min + B to C = 30 min + C to D = 45 min). There is a way for us to lower convergence time. It's called inter-site change notifications and it's not turned on by default. Inter-site change notifications work just like regular change notifications except it traverses sites. Since the replication partner across the site is notified of changes, the intersite replication interval is effectively ignored. The originating DC will notify the DC in the other site that it has a change just like it does within a site.  When you implement this setting, you need to have good links between these sites. I would recommend that any latency less than 500ms is good enough for inter-site change notifications. Most modern environments that I have seen can turn on inter-site change notifications without any issues, but they are either unaware of the setting or they think their links need to be better.

    Notification Delay

    So with change notification turned on in our sample design, we should have a pretty quick convergence time. But, it's still not instantaneous. But why not? There are a couple factors that would cause replication delays that I didn't mention earlier in our example. When change notifications are used, the DC's partners aren't notified immediately when a change is made. In Windows 2003, there is a 15 second delay before the first replication partner is notified that there is a change (in Windows 2000, the first delay is 300 seconds). After the first delay, the notification delay to other partners decreases to 3 seconds (in Windows 2000, subsequent delays are 30 seconds). This is true for all change notifications. So lets take another look at our sample design. Except this time, let's examine the replication partners

    Site Link Replication Partner 1 Replication Partner 2 Replication Interval
    Site A - Site B DC2 DC3 0
    Site B - Site C DC4 DC5 0
    Site C - Site D DC6 DC7 0

    So what's going to happen when an originating write occurs on DC1? Intersite change notifications are turned on now, so the replication interval is effectively 0. But since DC2 is the bridgehead to Site B, DC2 needs the change before it can replicate it. So the change is made on DC1. 15 seconds pass and DC2 is notified of the change. DC2 initiates replication and gets the change. Now what? Now DC2 waits another 15 seconds before notifying it's first replication partner that it has a change to replicate. So another 15 seconds pass before DC3 is notified. Then DC3 waits 15 seconds to notify DC4. And so on ... So by the time DC8 receives the change, approximately 105 seconds have passed, even though intersite change notifications are turned on.

    Urgent Replication

    Still, a convergence time of under 2 minutes is pretty good. But what about in the scenario of an account lockout? It's entirely possible that a user could hit a Domain Controller that the lockout hasn't replicated to yet. This is what urgent replication helps with. Urgent replication bypasses the notification delay and processes the change notifications immediately. This only affects change notifications. If you don't have change notifications on between sites, replication still honors the replication interval on the site link. So in the case of an account lockout, it's possible to have an almost instantaneous replication to DC8.

    Password Changes

    This is just one scenario that illustrates urgent replication. Password changes sort of break the rules. When a password is changed, there is an immediate replication to the PDC Emulator. This is different than urgent replication because it occurs immediately without any regard to the inter-site replication interval.

    There is a reason why the password change is immediately replicated to the PDC Emulator. If a user changes their password and then immediately logs on against another DC in a different site, the logon would probably fail because the other DC wouldn't yet have the change. AD takes this scenario into account. When there is an invalid password, the DC passes the authentication back to the PDC Emulator because it's going to have a copy of the latest password. If the PDC Emulator authenticates him successfully then the logon is processed. This happens behind the scenes and does not increment the bad password count attribute.

    Urgent replication is different than immediate replication and on-demand replication, so be careful not to confuse them. The key takeaway here is that urgent replication does not guarantee immediate convergence. Urgent replication only impacts the delay in change notifications.

  • WS08 AD Database Mounting Tool

    With Windows Server 2008's release, there has been a lot of discussion around the use of Read-Only Domain Controllers and AD Domain Services running on Server Core. Yet, one of the more interesting features that I find that a lot of people are overlooking is DSAMAIN.EXE (AD Database Mounting Tool). If you've used ADAM (now AD LDS) in the past,  you'll recognize DSAMAIN.EXE as the process that ADAMDSA.DLL runs under. This is ADAM's equivalent of NTDSA.DLL running under LSASS.EXE on a Domain Controller.

    ADAM has really paved the way for portable directory services on Windows. Although we may never see the full separation of Active Directory Domain Services running as a service (because of the security implications of running outside of LSASS), we are one step closer. In Windows Server 2008, AD DS is instantiated under a service called NTDS (with the display name of "Active Directory Domain Services"). So now, AD DS can be restarted without having to reboot the DC.

    Building on the portable directory concept, AD DS took a page from the book on ADAM and implemented what is called the AD Database Mounting Tool (DBMT). With the DBMT, you can actually mount a backup of AD DS under a different set of ports and have read-only access to your backups through LDAP. Just like how multiple instances of ADAM can run on the same machine under different ports, snapshots of NTDS.DIT can now do so as well. This provides read-only access to an offline copy of AD, but only through LDAP. Remember, this instance is not running in LSASS protected memory, so we don't want it issuing tickets or authenticating anyone - or doing anything else other than act as a vanilla directory service, for that matter.

    So what are the scenarios that can be exposed in this situation? So let's say that someone on the MIIS team just replaced the displayName attribute of every user object in the domain with "John Smith". Using NTDSUTIL, you can mount a copy of a previous snapshot to an alternate port and easily export the displayName attribute for every user object that was changed. These values can then be imported into the running instance of AD DS. Let's walk through the scenario:

    Step 1: Take a Snapshot

    So first, you need a VSS snapshot of the volume that the DIT is on. For our purposes, we'll take the snap using NTDSUTIL. So log on to your WS08 DC and open up a command prompt. Run the following command:

    ntdsutil "Activate Instance NTDS" snapshot create quit quit

    NTDSUTIL Snapshot

    You could also run NTDSUTIL and run each command separately to drill down through the menus, but you can schedule the above one-liner to run every night in a scheduled task.

    Step 2: Mount the Snapshot

    Now that you have a snapshot, you need to mount it so you can have access to NTDS.DIT. To mount the snapshot that we took in the previous step, we'll use NTDSUTIL again. First, you can list the snapshots that you have available:

    ntdsutil snapshot "list all" quit quit

    NTDSUTIL List snaps

    After you target which snapshot you want to mount, you can reference it using the snapshot index. FYI - NTDSUTIL requires that the "list" command be run in the same session that you mount the snapshot. So in order to mount the snapshot with a one-liner, you will need to run "list all" first.

    ntdsutil snapshot "list all" "mount 11" quit quit

    NTDSUTIL Mount Snapshot

    Note the path that it was mounted under: "C:\$SNAP_200803060936_VOLUMEC$". This coincides with the date and time that the snapshot was taken, as well as the volume that was snapped.

    Step 3: Mount the DIT

    In the last two steps, we've just been making the actual NTDS.DIT backup available to us. We can now access the DIT with the following path (assuming you used the default database path when running DCPROMO): "C:\$SNAP_200803060936_VOLUMEC$\Windows\NTDS\NTDS.DIT.

    Now, we'll use DSAMAIN.EXE (the Database Mount Tool - DBMT) to mount the DIT. There are a couple of things to note here. First, ensure that you put in the correct path to the NTDS.DIT file that you are mounting. Second, you have to give the DBMT a unique port to service LDAP requests on. In this example, we'll use 10389. What actually happens here is that the DBMT will expose the directory on LDAP, LDAP/SSL, GC, and GC/SSL. If can feed the command the different ports that you want to use for each protocol connection, but if you just give it one port (i.e. 10389), it will mount the subsequent listeners numerically. So if you specific 10389 for the LDAP port, this is what you end up with:

    • LDAP: 10389
    • LDAP/SSL: 10390
    • GC: 10391
    • GC/SSL: 10392

    Here's the command to mount the DIT:

    dsamain -dbpath C:\$SNAP_20080306_VOLUMEC$\Windows\NTDS\ntds.dit -ldapport 10389

    A funny thing happens next. The only thing that will actually indicate that the DIT is mounted is the message "Microsoft Active Directory Domain Services startup complete":

    DSAMAIN Mount DIT

    Do not close the command prompt. As long as the DBMT is running, you can access the directory over LDAP on the port you specified. To prove it, let's run ADSIEdit.

    ADSIEdit Snapped DIT

    Step 4: Grab the Data

    Now that we have access to a snapshot of the DIT, we can just export the data that we need. There are a million ways to do this. I'm a big fan of VBScript, so let's use the following script to pull the data out and write it to TSV (Tab Separated Values) file. We'll go through each user account and export the samAccountName and displayName attributes to the TSV. Remember, we're connecting to port 10389.

    '--------------------------------------------------------------------------
    ' NAME:        export-attr.vbs
    ' DATE:        3/6/2008
    ' DESCRIPTION: Connects to a directory service provider on the specified
    '              port and exports a list of attributes for each user object
    '              in the directory to a tab-separated values file.
    ' AUTHOR:      Ken St. Cyr
    '--------------------------------------------------------------------------
    
    Option Explicit
    
    ' Define our parameters
    CONST LDAPPORT = 10389
    CONST DCNAME = "localhost"
    CONST ATTRIBUTES = "samAccountName,displayName"
    CONST OUTPUT_FILE = "attribute_backup.tsv"
    
    ' Create the necessary objects for writing to a file
    Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
    Dim objFile : Set objFile = objFSO.OpenTextFile(OUTPUT_FILE, 8, True)
    
    ' Get the RootDSE for the directory on the port that we want
    Dim objRootDSE : Set objRootDSE = GetObject("LDAP://" & DCNAME & ":" & _
    LDAPPORT & "/RootDSE") ' Create the connection object for the AD provider Dim objConnection : Set objConnection = CreateObject("ADODB.Connection") objConnection.Provider = "ADsDSOObject" objConnection.Open "Active Directory Provider" ' Define the search to execute Dim objCommand : Set objCommand = CreateObject("ADODB.Command") objCommand.CommandText = "<LDAP://" & DCNAME & ":" & LDAPPORT & "/" & _
    objRootDSE.Get("defaultNamingContext") & ">;(&objectCategory=user);" & _
    ATTRIBUTES & ";subtree" objCommand.ActiveConnection = objConnection ' Execute the search Dim objRecordSet : Set objRecordSet = objCommand.Execute objRecordSet.MoveFirst ' Go through each result about output the attributes to a Tab-Separated file While Not objRecordSet.EOF Dim strSAMAccountName : strSAMAccountName = objRecordSet.Fields("samaccountname") Dim strDisplayName : strDisplayName = objRecordSet.Fields("displayName") objFile.WriteLine strSAMAccountName & vbtab & strDisplayName objRecordSet.MoveNext Wend objFile.Close WScript.Echo objRecordSet.RecordCount & " entries written to " & OUTPUT_FILE

    Step 5: Dismount the DIT

    Now that we have the data, we can get out and reverse everything we just did. To dismount the DIT, its simply a matter of pressing CTRL-C at the command window for the DBMT. You'll get a message indicating that the DS shut down successfully.

    DSAMAIN Dismount

    Step 6: Unmount the Snapshot

    The last thing we need to do is to unmount the snapshot. Again, this can be done through NTDSUTIL. The same concept as step 2 applies here, so you are required to perform a "list mounted" before we can actually perform the unmount command.

    ntdsutil snapshot "list mounted" "unmount 1" quit quit

    NTDSUTIL Unmount

    And that's it. I know this process may seem a little confusing at first, but after running through it a few times in the lab, you'll get the hang of it. Besides, it's MUCH better than the alternative - taking down the DC (or standing up an offline DC), restoring from a backup, rebooting into DSRM, and then exporting the attributes. At least with the DBMT, you can use a snapshot and perform it on a live DC using an alternate port - and the DC remains functional the entire time.

    -

    Thus concludes the first post in this new blog. I had a few other blogs out there running with various topics, but I've decided to collapse them all into this one. The problem is that I forgot to back up the articles that I wrote before I took the blogs offline (doh!), so most of my content is gone. When/if I find it, I'll repost it all here. In the mean time, I'll be moving over material from some of my other articles.