如何用Shell脚本实现IP段的DNS反向查询
Got it, I totally get the pain of manually running dig -x for every IP in a range—super inefficient. Let's build some shell scripts to automate this for both CIDR blocks and start/end IP ranges.
Solution 1: Query a CIDR Range
This script uses prips (a lightweight tool to generate IP lists from CIDR) to iterate through every IP in the range, runs a reverse DNS lookup, and only outputs results where a PTR record exists.
First, install prips if you don't have it:
- Debian/Ubuntu:
sudo apt install prips - RHEL/CentOS:
sudo yum install prips
Here's the script:
#!/bin/bash # Check if we got a CIDR argument if [ $# -ne 1 ]; then echo "Usage: $0 <CIDR-block>" echo "Example: $0 192.168.1.0/24" exit 1 fi CIDR=$1 # Generate all IPs in the CIDR, then loop through each prips "$CIDR" | while read -r IP; do # Use dig +short to get only the PTR record (no extra noise) PTR_RECORD=$(dig -x "$IP" +short) # Only print if we got a valid PTR record if [ -n "$PTR_RECORD" ]; then echo "$IP -> $PTR_RECORD" fi done
How it works:
- Checks that you provided exactly one CIDR block as input
- Uses
pripsto expand the CIDR into a list of individual IPs - For each IP, runs
dig -xwith+shortto get a clean PTR record (if it exists) - Prints the IP and its corresponding PTR record only when the record exists
Solution 2: Query a Start-to-End IP Range
If you have a specific start and end IP instead of a CIDR, this script converts IPs to integers to easily loop through the range, then converts them back to IP format for lookups.
#!/bin/bash # Helper function: Convert IP address to a 32-bit integer ip_to_integer() { local IFS=. read -r oct1 oct2 oct3 oct4 <<< "$1" echo $((oct1 * 256**3 + oct2 * 256**2 + oct3 * 256 + oct4)) } # Helper function: Convert 32-bit integer back to IP address integer_to_ip() { local num=$1 echo "$((num / 256**3)).$((num % 256**3 / 256**2)).$((num % 256**2 / 256)).$((num % 256))" } # Check if we got start and end IP arguments if [ $# -ne 2 ]; then echo "Usage: $0 <start-IP> <end-IP>" echo "Example: $0 192.168.1.1 192.168.1.100" exit 1 fi START_IP=$1 END_IP=$2 # Convert start/end IPs to integers for easy looping START_INT=$(ip_to_integer "$START_IP") END_INT=$(ip_to_integer "$END_IP") # Loop through every integer in the range, convert back to IP, and run lookup for ((i=START_INT; i<=END_INT; i++)); do CURRENT_IP=$(integer_to_ip "$i") PTR_RECORD=$(dig -x "$CURRENT_IP" +short) if [ -n "$PTR_RECORD" ]; then echo "$CURRENT_IP -> $PTR_RECORD" fi done
How it works:
- Two helper functions handle converting between IP strings and integers (makes looping through ranges trivial)
- Validates that you provided exactly two IPs (start and end)
- Converts the start/end IPs to integers, then loops through every number in between
- Converts each integer back to an IP, runs the reverse lookup, and prints results with existing PTR records
Speed Optimization: Parallel Lookups
By default, these scripts run lookups one at a time. To speed things up, you can use xargs to run multiple dig queries in parallel. For example, modifying the CIDR script to run 10 parallel queries:
prips "$CIDR" | xargs -P 10 -I {} sh -c ' PTR=$(dig -x {} +short) if [ -n "$PTR" ]; then echo "{} -> $PTR" fi '
Adjust the -P 10 value to control how many parallel queries you want (higher = faster, but don't overload your DNS server or get rate-limited).
内容的提问来源于stack exchange,提问作者SunilGhargaonkar

