Skip to content

Instantly share code, notes, and snippets.

@AlexAtkinson
Last active October 4, 2023 19:33
Show Gist options
  • Save AlexAtkinson/b3f18301d9dea5c2eb3f452260a03591 to your computer and use it in GitHub Desktop.
Save AlexAtkinson/b3f18301d9dea5c2eb3f452260a03591 to your computer and use it in GitHub Desktop.
A quick dns propagation checker in BASH.
#!/usr/bin/env bash
# --------------------------------------------------------------------------------------------------
# dnsPropagationCheck.sh
#
# NOTE: Requires dnsServers.txt. Example:
#
#8.8.8.8 Google_1
#8.8.4.4 Google_2
#9.9.9.9 Quad9_1
#149.112.112.112 Quad9_2
#77.88.8.1 Yandex_1
#77.88.8.8 Yandex_2
#208.67.222.222 OpenDNS_1
#208.67.220.220 OpenDNS_2
#209.244.0.3 Level3_1
#209.244.0.4 Level3_2
#216.146.35.35 DYN_1
#216.146.36.36 DYN_2
#8.26.56.26 Comodo_1
#8.20.247.20 Comodo_2
#64.6.64.6 UltraDNS_1
#64.6.65.6 UltraDNS_2
#1.1.1.1 Cloudflare_1
#1.0.0.1 Cloudflare_2
#185.228.168.9 CleanBrowsing_1
#185.228.169.9 CleanBrowsing_2
#64.6.64.6 Verisign_1
#64.6.65.6 Verisign_2
#176.103.130.130 AdGuard_1
#176.103.130.131 AdGuard_2
#
# --------------------------------------------------------------------------------------------------
# Help
# --------------------------------------------------------------------------------------------------
help="\
NAME
dnsPropagationCheck.sh
SYNOPSIS
${0##*/} [-h] [-t \e[04mtype\e[0m] [-d \e[04mdomain\e[0m]
DESCRIPTION
Retrieves the TTL of a DNS record from across many DNS servers.
The following options are available:
-h Print this menu.
-t \e[04mtype\e[0m
Specify the record type to check.
-d \e[04mdomain\e[0m
Specify the domain name to check.
EXAMPLES
The following retrieves the TTL of www.nike.com from accross man DNS servers.
./dnsPropagationCheck.sh -t cname -d www.nike.com
"
printHelp() {
echo -e "$help" >&2
}
# --------------------------------------------------------------------------------------------------
# Sanity (1/2)
# --------------------------------------------------------------------------------------------------
if [[ "$1" != '-h' && $# -lt 4 ]]; then
printHelp
exit 1
fi
if [[ ! -f dnsServers.txt ]]; then
echo -e "\e[01;31mERROR\e[0m: The file 'dnsServers.txt' is required."
exit 1
fi
# --------------------------------------------------------------------------------------------------
# Arguments
# --------------------------------------------------------------------------------------------------
OPTIND=1
while getopts "ht:d:" opt; do
case $opt in
h)
printHelp
exit 0
;;
t)
arg_t='set'
arg_t_val=("$OPTARG")
;;
d)
arg_d='set'
arg_d_val=("$OPTARG")
;;
*)
echo -e "\e[01;31mERROR\e[00m: Invalid argument!"
printHelp
exit 1
;;
esac
done
shift $((OPTIND-1))
# --------------------------------------------------------------------------------------------------
# Sanity (2/2)
# --------------------------------------------------------------------------------------------------
if [[ "$arg_t" == 'set' && "$arg_d" != 'set' ]]; then
echo -e "\e[01;31mERROR\e[0m: Both the DNS record type and domain name must be specified."
printHelp
exit 1
fi
if [[ "$arg_t" != 'set' && "$arg_d" == 'set' ]]; then
echo -e "\e[01;31mERROR\e[0m: Both the DNS record type and domain name must be specified."
printHelp
exit 1
fi
# --------------------------------------------------------------------------------------------------
# Variables
# --------------------------------------------------------------------------------------------------
recordType="$arg_t_val"
domain="$arg_d_val"
printf "\e[04mQuery Summary:\e[0m\n"
printf " Record Type: $recordType\n"
printf " Record Name: $domain\n\n"
col1="\e[04mServer\e[0m"
col2="\e[04mTTL\e[0m"
col3="\e[04mValue\e[0m"
printf "$col1"
printf '%*s' "$((${COLUMNS}-$((${COLUMNS}-$(wc -c<<<$col1)+60))))"
printf "$col2"
printf '%*s' "$((${COLUMNS}-$((${COLUMNS}-$(wc -c<<<$col2)+6))))"
printf "$col3\n"
while read -r line; do
server=$(awk '{print $1}' <<< $line)
name=$(echo $line | cut -d' ' -f2- | awk '{$1=$1;print}')
unset ttl
if nc -zv -w 1 $server 53 2>/dev/null; then
response=$(dig ${recordType} @${server} +tcp +noall +answer ${domain} | head -n1)
ttl=$(echo "$response" | awk '{print $2}')
[[ -z $ttl ]] && ttl='na'
val=$(echo "$response" | awk '{print $5}')
[[ -z $val ]] && val='na'
printf "$server"
printf '%*s' "$((${COLUMNS}-$((${COLUMNS}-$(wc -c<<<$server)+19))))"
printf "$name"
printf '%*s' "$((${COLUMNS}-$((${COLUMNS}-$(wc -c<<<$name)+31))))"
printf "$ttl"
printf '%*s' "$((${COLUMNS}-$((${COLUMNS}-$(wc -c<<<$ttl)+13))))"
printf "$val\n"
else
printf "ERROR: DNS server ${server} (${name}) could not be reached.\n"
fi
done <<< $(cat dnsServers.txt)
@AlexAtkinson
Copy link
Author

AlexAtkinson commented Feb 21, 2023

Outputs like:

$ ./dnsPropagationCheck.sh -t a -d  nike.com
Query Summary:
  Record Type: a
  Record Name: nike.com

Server                                          TTL         Value
8.8.8.8           Google_1                      60          13.33.165.56
8.8.4.4           Google_2                      60          13.33.165.56
9.9.9.9           Quad9_1                       60          108.156.120.116
149.112.112.112   Quad9_2                       60          108.156.120.116

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment