Finding duplicate DNS records
The following examples use dnscmd.exe, which assumes Windows 2000/2003 DNS, but you could use any input, as long as it contains a name and an IP.
The two commands:
- dnscmd %dnsServer% /enumrecords test.local @ /additional /continue | find /i /v "Aging:" | find /i "192.168" > DNSRecords.txt
- echo. > DuplicateIPs.txt & (for /f "tokens=1,4" %i in (DNSRecords.txt) do @if "%j" NEQ "" @find /i "%j" DuplicateIPs.txt >nul & if errorlevel 1 for /f "tokens=1" %m in ('"findstr /i "%j$" DNSRecords.txt | find /i /c "%j""') do @if %m GTR 1 (@echo %j,%m: & findstr /i "%j$" DNSRecords.txt & echo.) >> DuplicateIPs.txt) & type DuplicateIPs.txt
The first command uses dnscmd to enumerate the records from the root of the test.local zone and exclude aging (dynamic DNS) records. The last find command further filters the output by IP, which can be useful when targeting specific subnets/sites. You might also want to check aging dynamic records instead of static to see how well scavenging is working – if you do, just change the tokens to 1,5 instead of 1,4 (as the aging data is another token separating the name and IP).
The second command:
- Creates a new file called DuplicateIPs.txt in the current working directory
- Iterates through each line in the DNS record dump, extracting the first and fourth token (Name and IP)
- The commands in the first FOR loop check there is a value, then check the value hasn't already been processed in the duplicate list (otherwise you'd have duplicates of each duplicate) and then counts the duplicates and appends them to the file.
- The final command types the duplicate IP file created by the for loop iteration.
For example, supposing your DNS export contained the following records:
printer1 3600 A 192.168.10.100 printer2 3600 A 192.168.10.101 printer3 3600 A 192.168.10.100 printer4 3600 A 192.168.10.102 printer5 3600 A 192.168.10.103 printer6 3600 A 192.168.10.100 printer7 3600 A 192.168.10.102
After running the second command above, a file called DuplicateIPs.txt would be created and then typed to the prompt:
192.168.10.100,3: printer1 3600 A 192.168.10.100 printer3 3600 A 192.168.10.100 printer6 3600 A 192.168.10.100 192.168.10.102,2: printer4 3600 A 192.168.10.102 printer7 3600 A 192.168.10.102
The command below is modified to report duplicate names instead of IP addresses. This was done by using the first token (%i) instead of the second (%j), and modifying the findstr command to use a literal string search ending with a space rather than the regular expression EOL:
echo. > DuplicateIPs.txt & (for /f "tokens=1,4" %i in (DNSRecords.txt) do @if "%i" NEQ "" @find /i "%i" DuplicateIPs.txt >nul & if errorlevel 1 for /f "tokens=1" %m in ('"findstr /i /c:"%i " DNSRecords.txt | find /i /c "%i""') do @if %m GTR 1 (@echo %i,%m: & findstr /i /c:"%i " DNSRecords.txt & echo.) >> DuplicateIPs.txt) & type DuplicateIPs.txt
If you wanted a summary rather than the detail of each duplicate, you could also run the following command:
echo. > DuplicateIPSummary.txt & (for /f "tokens=1,4" %i in (DNSRecords.txt) do @if "%j" NEQ "" @find /i "%j" DuplicateIPSummary.txt >nul & if errorlevel 1 for /f "tokens=1" %m in ('"findstr /i "%j$" DNSRecords.txt | find /i /c "%j""') do @if %m GTR 1 (@echo %j,%m) >> DuplicateIPSummary.txt) & type DuplicateIPSummary.txt
In the example above, this would produce the following report:
I use this sort of command to generate reports on duplicates, in this case from DNS, but it could also be useful in DHCP, WINS, or any number of Active Directory objects/attributes. People (myself included) are often wary of automated processes that make changes, but this is an excellent example of how powerful read-only automated commands can be – you can take thousands of objects and produce a report in seconds to quickly identify inconsistencies in an environment.