Skip to main content

How to Perform a Reverse DNS Lookup in Batch Script

A standard DNS lookup turns a name into an IP. A Reverse DNS Lookup (rDNS) does the opposite: it turns an IP address (like 8.8.8.8) into a human-readable hostname (like dns.google). This is essential for security auditing, as it helps you identify who is actually connecting to your server. If you see an unknown IP in your logs, a reverse lookup can tell you if it's a legitimate bot (like Bingbot), a corporate office, or a suspicious home connection. A Batch script can automate this using nslookup or the ping -a flag.

This guide will explain how to resolve IPs back to hostnames.

Method 1: Using NSLOOKUP (The Professional Way)

nslookup is the standard tool for querying name servers. By simply passing an IP address instead of a domain name, it triggers a "Pointer" (PTR) record query.

@echo off
setlocal enabledelayedexpansion

set "TargetIP=8.8.8.8"

:: Ensure temp directory is valid
set "TempDir=%TEMP%"
if not exist "%TempDir%" set "TempDir=%CD%"
set "TempFile=%TempDir%\rdns_result.tmp"

echo [DNS] Performing Reverse Lookup for %TargetIP%...
echo.

set "ResultHost="

ipconfig /flushdns >nul 2>&1

nslookup %TargetIP% > "%TempFile%" 2>&1

:: Look for "Name:" line (PTR result)
for /f "tokens=2 delims=:" %%a in ('findstr /i "Name:" "%TempFile%"') do (
set "ResultHost=%%a"
set "ResultHost=!ResultHost:~1!" :: trim leading space
)

:: Fallback for "name =" format
if not defined ResultHost (
for /f "tokens=2 delims==" %%a in ('findstr /i "name =" "%TempFile%"') do (
set "ResultHost=%%a"
set "ResultHost=!ResultHost:~1!"
)
)

if not defined ResultHost (
echo [INFO] No PTR record found for %TargetIP%.
echo.
type "%TempFile%"
) else (
echo [RESULT] %TargetIP% resolves to: !ResultHost!
)

del "%TempFile%" >nul 2>&1

pause
endlocal

Output:

[DNS] Performing Reverse Lookup for 8.8.8.8...

[RESULT] 8.8.8.8 resolves to: dns.google
Why capture to a temp file?

Reverse DNS output from nslookup varies significantly between Windows versions. Some show Name: dns.google, others show name = dns.google. By capturing the full output, we can try multiple parsing patterns and fall back to displaying the raw output if parsing fails.

Method 2: Using PING (The Fast Shortcut)

The ping command has a useful flag -a (resolve addresses to hostnames). This is often faster for local network discovery.

@echo off
setlocal enabledelayedexpansion

set "IP=192.168.1.1"

echo [SCAN] Identifying device at %IP%...
echo.

set "hostname="

:: -a resolves the IP to a hostname in the "Pinging hostname [IP]" line
:: Extract the hostname from between "Pinging " and " ["
for /f "tokens=2" %%a in ('ping -a -n 1 -w 1000 %IP% 2^>nul ^| findstr /i "Pinging"') do (
set "hostname=%%a"
)

:: Check if we got a hostname or just the IP echoed back
if not defined hostname (
echo [INFO] Device at %IP% did not respond.
) else if /i "!hostname!"=="%IP%" (
echo [INFO] Device at %IP% is active but has no reverse DNS name.
) else (
echo [RESULT] %IP% is: !hostname!
)

pause
endlocal
Why check if hostname equals the IP?

When ping -a cannot resolve a name, it echoes the IP address itself in the "Pinging" line (e.g., Pinging 192.168.1.1). Without this check, the script would falsely report the IP as the "hostname."

Method 3: Bulk Lookup from a File

If you have a list of suspicious IPs from your server logs, resolve them all at once.

@echo off
setlocal enabledelayedexpansion

set "InputFile=ip_list.txt"
set "OutputFile=%USERPROFILE%\rdns_results.csv"

if not exist "%InputFile%" (
echo 8.8.8.8 > "%InputFile%"
echo 1.1.1.1 >> "%InputFile%"
echo 208.67.222.222 >> "%InputFile%"
echo [INFO] Created sample %InputFile%
echo.
)

echo [AUDIT] Bulk Reverse DNS Lookup
echo Input: %InputFile%
echo Output: %OutputFile%
echo.

echo IP,Hostname,Status > "%OutputFile%"

set "Count=0"
set "Resolved=0"

for /f "usebackq delims=" %%i in ("%InputFile%") do (
if not "%%i"=="" (
set /a Count+=1
set "ip=%%i"
set "host="

echo [!Count!] Looking up !ip!...

for /f "tokens=2 delims=[]" %%h in ('
ping -a -n 1 -w 1000 !ip! 2^>nul ^| findstr /i "Pinging"
') do (
set "host=%%h"
)

if defined host (
if /i "!host!"=="!ip!" (
echo No PTR record
echo !ip!,N/A,No PTR>>"%OutputFile%"
) else (
echo !host!
echo !ip!,!host!,Resolved>>"%OutputFile%"
set /a Resolved+=1
)
) else (
echo Unreachable / No PTR
echo !ip!,N/A,Unreachable>>"%OutputFile%"
)
)
)

echo.
echo ==========================================
echo Processed: !Count! Resolved: !Resolved!
echo ==========================================
echo.
echo [DONE] %OutputFile%

pause
endlocal
endlocal

Output:

[AUDIT] Bulk Reverse DNS Lookup
Input: ip_list.txt
Output: C:\Users\David\rdns_results.csv

[1] Looking up 8.8.8.8 ...
8.8.8.8
[2] Looking up 1.1.1.1 ...
1.1.1.1
[3] Looking up 208.67.222.222 ...
208.67.222.222

==========================================
Processed: 3 Resolved: 3
==========================================

[DONE] C:\Users\David\rdns_results.csv

Method 4: PowerShell High-Performance Lookup

For large IP lists, PowerShell's Resolve-DnsName is significantly faster than looping nslookup and handles errors gracefully.

@echo off
setlocal

set "InputFile=ip_list.txt"
set "OutputFile=%USERPROFILE%\rdns_powershell.csv"

echo [AUDIT] High-performance reverse DNS lookup...
echo.

:: Single IP quick lookup
echo --- Single IP Test ---
powershell -NoProfile -Command ^
"try {"^
" $result = Resolve-DnsName '8.8.8.8' -Type PTR -ErrorAction Stop;"^
" Write-Host (' 8.8.8.8 -> ' + $result.NameHost)"^
"} catch {"^
" Write-Host ' 8.8.8.8 -> No PTR record found'"^
"}"

echo.

:: Bulk lookup from file
if exist "%InputFile%" (
echo --- Bulk Lookup from %InputFile% ---
echo.

powershell -NoProfile -Command ^
"$ips = Get-Content '%InputFile%' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' };"^
"$results = foreach ($ip in $ips) {"^
" try {"^
" if ($ip -notmatch '^[0-9a-fA-F:.]+$') { throw 'Invalid IP' };"^
" $r = Resolve-DnsName -Name $ip -Type PTR -ErrorAction Stop;"^
" $hostname = $r.NameHost;"^
" Write-Host (' [OK] ' + $ip + ' -> ' + $hostname);"^
" [PSCustomObject]@{ IP=$ip; Hostname=$hostname; Status='Resolved' }"^
" } catch {"^
" $msg = $_.Exception.Message;"^
" Write-Host (' [NONE] ' + $ip + ' -> ' + $msg);"^
" [PSCustomObject]@{ IP=$ip; Hostname='N/A'; Status='Failed' }"^
" }"^
"};"^
"$results | Export-Csv -Path '%OutputFile%' -NoTypeInformation;"^
"$ok = ($results | Where-Object Status -eq 'Resolved').Count;"^
"Write-Host '';"^
"Write-Host ('Resolved: ' + $ok + ' of ' + $results.Count);"^
"Write-Host ('Saved to: %OutputFile%');"
) else (
echo [INFO] No %InputFile% found. Create one with IP addresses (one per line^) for bulk lookup.
)

pause
endlocal
Why -Type PTR explicitly?

Without specifying the record type, Resolve-DnsName may return other record types. Using -Type PTR ensures you get only the reverse DNS pointer record: the actual hostname associated with the IP.

How to Avoid Common Errors

Wrong Way: Assuming Every IP Has a Name

Many home internet connections, cloud instances, and internal devices do not have a PTR record configured. If your script doesn't find a name, it doesn't mean the IP is "fake": it just means the DNS administrator hasn't set up a reverse record.

Correct Way: Always check for empty results and provide a clear explanation:

if not defined ResultHost (
echo No PTR record found. This is normal for many IPs.
)

Wrong Way: Using ping -a Without Checking for IP Echo

When ping -a cannot resolve a hostname, it echoes the raw IP address in the "Pinging" line. A script that blindly captures the second token will report the IP itself as the "hostname."

Correct Way: Compare the captured value against the original IP:

if /i "!hostname!"=="%IP%" (
echo No reverse DNS name available.
) else (
echo Hostname: !hostname!
)

Wrong Way: Not Clearing Variables Before Parsing

If a lookup fails, your variable retains the value from the previous successful lookup, making you think the current IP resolved to the same hostname.

Correct Way: Always clear the variable before each lookup:

set "ResultHost="
:: ... perform lookup ...
if not defined ResultHost echo Lookup failed.

Problem: Parsing "Non-authoritative answer"

Like forward lookups, nslookup includes header noise in the output. The "Name:" line for the DNS server itself can be confused with the actual result.

Solution: Capture the full output to a temp file and parse carefully, or use ping -a (Method 2) or PowerShell (Method 4) for cleaner output.

Problem: nslookup Errorlevel Is Unreliable

nslookup returns errorlevel 1 for non-authoritative answers, which is the standard response for most queries. You cannot use %errorlevel% to determine success or failure.

Solution: Parse the actual output text for results or failure strings instead of checking %errorlevel%.

Best Practices and Rules

1. Security Log Analysis

Use this script to analyze your server's "Failed Login" logs. Automatically resolving attacker IPs can tell you if the source is a cloud VPS (like AWS or Azure), a known bot network, or a specific organization.

2. DNS Cache

If you just set up a PTR record, Windows might not see it yet. Use ipconfig /flushdns to clear your local cache before running the audit:

ipconfig /flushdns >nul 2>&1

3. Check Internal AD

On a corporate network, your internal DNS server (Active Directory) should have reverse lookup zones configured. If ping -a fails to resolve the name of a PC in your office, your AD DNS reverse lookup zone may be incomplete.

4. Query a Specific DNS Server

To bypass your local DNS and check the authoritative PTR record:

nslookup 8.8.8.8 1.1.1.1

This queries Cloudflare's DNS (1.1.1.1) for the reverse record of 8.8.8.8.

5. PTR Records Are Not Guaranteed

Unlike forward DNS (A records), reverse DNS (PTR records) are optional. Many legitimate services and ISPs simply don't configure them. The absence of a PTR record is informational, not alarming.

6. Always Use setlocal / endlocal

Without setlocal, every variable your script creates persists in the parent shell session, causing potential conflicts when running multiple scripts in sequence.

Conclusions

Performing reverse DNS lookups is a powerful forensic and troubleshooting capability. By transforming "cold" IP addresses into recognizable hostnames, you gain a clear understanding of your network's actors and infrastructure. This visibility is essential for maintaining a secure network, identifying unauthorized devices, and providing professional context to your system audit reports.