Backing up and Restoring Domain-Based DFS Namespaces

I had a question for a customer recently which needed some investigation, as the seemingly “easy steps” to export and import DFSN configurations didn’t do what either of us expected.

KB969382 lists the actions to take in the event of your DFS Namespace going west. Option 2 was the one we were looking at as we wanted to create regular DFS-N backups to be used in any DFS-N related emergency.

It seemed simple enough, run this command to backup your configuration:

dfsutil root export \domain.nameDFSN DFSN-root.txt

And when disaster strikes, just run this command to put it all back again:

dfsutil  root import set DFSN-Root.txt \domain.nameDFSN

However, no matter what the DFS-N emergency we created in the lab, the import would always fail citing “element not found”.

The problem was that we were breaking the DFS-N root (on purpose), but the export/import scenario requires you to have a working DFS-N root. And to get that, you’d need good system-state backups of both a DC and a DFS Namespace server. Which isn’t going to provide for a fast, efficient restore scenario in a large organisation.

So I started experimenting, and it seems that the objects in AD are easily copied and imported again using ldifde – there is no attachment to the object GUIDs (like there is say in a failover cluster). And once all the objects are back in AD, all the links and targets start working again as expected.

The same applies to the share and DFSN root information in the registry – a simple ‘reg save’ followed by a ‘reg restore’ will get that information back with the registry ACLs in tact.

So, I wrote 2 scripts (each fires of a second script to run directly on the DFS Namespace servers):

  1. The scheduled backup script deployed as a scheduled task to a central management server
  2. A restore script to be used in the case of any DFS-N emergency

Now, while the restore could be more targeted to allow you to chose the scenario to recover from (e.g. restore ONLY the objects in AD or DFS-N registry information on just 1 DFS-N server, or only one DFS-N root), I’ll leave it to you good reader to add that intelligence. This restore script restore the entire DFS-N configuration for all roots and to all DFS-N servers.

This will backup and restore both Windows 2000/2003 roots and Windows Server 2008 roots. It uses psexec from Sysinternals, available here. The reason it does this is to use reg save/reg restore, which capture ACLs on the registry keys and restores exactly the configuration which was backed up, rather than merging the configuration. While my testing shows that these reg keys do not have explicit permissions defined, you’re better safe than sorry.

Make sure and change any instances of “dc=domain,DC=name” and “\” to the domain name in your environment.


Main Job

rem Setup input file

if not exist .backupfiles mkdir .backup-files
if exist root-servers.txt del root-servers.txt


if exist servers.txt del servers.txt
dsquery * "CN=DFS-Configuration,CN=System,DC=domain,dc=name" -filter "(|(objectClass=fTDfs)(objectClass=msDFS-Namespacev2))" -attr name > allRoots.txt
for /F "tokens=1-3 skip=1 delims= " %%i IN (allRoots.txt) DO (
        dfsutil root \ | find /i "target" | find /i "%%i" >> %%i-serversRAW.txt
        for /F "tokens=2 delims=" %%u IN (%%i-serversRAW.txt) do  echo %%i;%%u >> root-servers.txt
        del %%i-serversRAW.txt

for /F "tokens=1,2 delims=; " %%i IN (root-servers.txt) DO echo %%j>> serversRAW.txt
sort serversRAW.txt /O serversSORTED.txt
for /F "Tokens=*" %%s in ('type serversSORTED.txt') do set record=%%s&call :output

del serversRAW.txt
del serversSORTED.txt


rem Backup

for /F %%i IN (servers.txt) DO (
    if not exist \%%ic$temp mkdir \c$temp
    copy .NSserverBackup.bat \%%ic$temp /Y
    psexec \%%i C:tempNSserverBackup.bat
    copy \%%ic$ /Y
    copy \%%ic$ /Y
    copy \%%ic$ /Y

ldifde -f .backup-filesdfs-export.ldf -v -d "CN=Dfs-Configuration,CN=System,DC=domain,dc=name" -l objectClass,remoteServerName,pKTGuid,pKT,msDFS-SchemaMajorVersion,msDFS-SchemaMinorVersion,msDFS-GenerationGUIDv2,msDFS-NamespaceIdentityGUIDv2,msDFS-LastModifiedv2,msDFS-Propertiesv2,msDFS-TargetListv2,msDFS-Ttlv2,msDFS-LinkPathv2,msDFS-LinkSecurityDescriptorv2,msDFS-Ttlv2,msDFS-Commentv2,msDFS-ShortNameLinkPathv2,msDFS-LinkIdentityGUIDv2 > .backup-filesldf-export.log

goto :EOF

if not defined previous_record goto write
if "%record%" EQU "%previous_record%" goto :EOF

@echo %record%>>servers.txt
set previous_record=%record%


cd temp

reg save HKLMSoftwareMicrosoftWindowsDFSRoots /y
reg save HKLMSystemCurrentControlSetServiceslanmanservershares /y
reg save HKLMSystemControlSet001Serviceslanmanservershares /y

The main backup job copies NSserverBackup.bat to each Namespace server and runs it from there.



Main Job

rem Check input files

if not exist allRoots.txt goto :EOF
if not exist servers.txt goto :EOF

rem clean up before restore

dsquery * "CN=DFS-Configuration,CN=System,DC=DC=domain,dc=name" -filter "(|(objectClass=fTDfs)(objectClass=msDFS-NamespaceAnchor))" | dsrm -q -subtree -noprompt
for /F %%i IN (servers.txt) DO (
               reg delete \%%iHKLMSoftwareMicrosoftWindowsDFSRoots /f
               reg delete \%%iHKLMSystemCurrentControlSetServiceslanmanservershares /f
               reg delete \%%iHKLMSystemControlSet001Serviceslanmanservershares /f
               reg add \%%iHKLMSoftwareMicrosoftWindowsDFSRoots /f
               reg add \%%iHKLMSystemCurrentControlSetServiceslanmanservershares /f
               reg add \%%iHKLMSystemControlSet001Serviceslanmanservershares /f

rem restore

ldifde -I -f .backup-filesdfs-export.ldf -k -v > .backup-filesdfs-import.log
for /F %%i IN (servers.txt) DO (
        copy \%%ic$ /Y
        copy \%%ic$ /Y
        copy \%%ic$ /Y
    copy .NSserverRestore.bat \%%ic$tempNSserverRestore.bat /Y
    copy .allRoots.txt \%%ic$tempallRoots.txt /Y
psexec @servers.txt C:tempNSserverRestore.bat


reg restore HKLMSoftwareMicrosoftDFSRoots
reg restore HLLMSystemCurrentControlSetServiceslanmanservershares
reg restore HLLMSystemControlSet001Serviceslanmanservershares
for /F "tokens=1-3 skip=1 delims= " %%i IN (allRoots.txt) DO dfsutil root forcesync \
net stop dfs && net start dfs

The main backup job copies NSserverRestore.bat to each Namespace server and runs it from there.

Comments (9)

  1. @Aldo – great to hear, thanks for the feedback

  2. @Reinhard: Thanks for pointing out the typo. I’ve edited the blog post to repair all incorrect references to the reg path.

  3. Aldo Funes says:

    Made it work, thanks for the great post man. It is awesome

  4. Anthony Balraj.S says:

    Thanks Craig, this helped me a lot and saved me sometime 🙂

  5. Rob Chesworth says:

    as per:
    It will fail on element not found if you don’t create the root first "Attempting the import before the root has been created will result in the error "Element not found." "

    Hope this helps someone – but great info nevertheless.

  6. Reinhard Bauer says:

    Thanks Craig. great post. The Reg-Path NSserverBackup.bat is not correct, HKLMSoftwareMicrosoftDFSRoots instead of HKLMSoftwareMicrosoftWindowsDFSRoots

  7. Faber says:

    This post is still valid in a 2012R2 Environment Domain?

  8. @Faber: There is no major changes to DFSN in Windows Server 2012 R2 and the commands used still exist in the 2012 R2 versions. So I can’t see why it wouldn’t work. Try it out (they’re sample scripts after all) and report your finding back so I can edit
    the blog to make it clear.

  9. Faber says:

    Thanks for the immediate feedback… I will give a try soon!

Skip to main content