Mini Shell
#!/bin/bash
#
# script: sdig (Supadig)
# author: terrenceh (based on joec's checkdns)
# description: digs up full existing DNS details on any valid domain
# + digs for entries in Google's public DNS w/ serial
# + digs for internal IMH/HUB NS & cluster A record entries w/ serial
# + a quick look at WHOIS
# usage: sdig <domain.tld> [or]
# sdig <email@domain.tld> [or]
# sdig <http://hostname.tld/some/page.ext> [or]
# sdig --about [or]
# sdig --help
#
VERSION=1.0
#
# info/usage
#
# header
DisplayHeader(){
# output:
echo
echo ' _ _ '
echo ' | |_| '
echo ' ___ _ _ ____ ____ __| |_ ____ '
echo ' / __| || | _ \/ _ \/ _ | |/ _ \'
echo ' \__ \ || | |_| ||_| | |_| | | |_| |'
echo ' |___/___/| .__/\__/_|\____|_|\__ |'" $VERSION "
echo ' | | __| |'" Terrence H"
echo ' |_| |____/'
echo
}
# about
DisplayInfo(){
# output:
echo
echo " SCRIPT: sdig (Supadig)"
echo " AUTHOR: Terrence H"
echo " DOES: Digs up full existing DNS details on any valid domain"
echo " + Digs for entries in Google's public DNS w/ serial"
echo " + Digs for internal IMH/HUB NS & cluster A record entries w/ serial"
echo " + A quick look at WHOIS"
}
# usage
DisplayUsage(){
# output:
echo
echo " USAGE: sdig <domain.tld> [or]"
echo " sdig <email@domain.tld> [or]"
echo " sdig <http://hostname.tld/some/page.ext> [or]"
echo " sdig --about [or]"
echo " sdig --help"
echo
echo
}
#
# main functions
#
# global vars
declare DOMAIN
declare ROOT_DOMAIN
declare ZONE
declare SECTION="|----------------------------------------------------------------|"
# check if root domain and/or if has its own zone
CheckIsRootDomain(){
# task: dertermine domain level
ROOT_DOMAIN=$(echo "$DOMAIN"|rev|cut -d\. -f1,2 -s|rev)
ZONE=$(dig "$DOMAIN" ns +noall +nocmd +authority|awk {'print $1'}|grep "\."|sed 's/.$//')
if [ -z "$ZONE" ]
then
ZONE="$DOMAIN"
fi
local dots=$(echo "$DOMAIN"|grep -o "\."|wc -l)
# output: formatting
echo
echo -n " $DOMAIN - "|tr "[:lower:]" "[:upper:]"
if [ "$dots" -eq 1 ]
then
echo -e "2nd-level! (has 1 dot)\n$SECTION"
elif [ "$dots" -eq 2 ]
then
echo -e "3rd-level! (has 2 dots)\n$SECTION"
elif [ "$dots" -gt 2 ]
then
echo -e "NOT a root domain! (has $dots dots)\n$SECTION"
fi
echo " Root Domain: $ROOT_DOMAIN"
echo " Zone: $ZONE"
echo
# cleanup root check
unset dots
}
# pull whois registrar and nameserver info (if available/results can be parsed)
FetchWhois(){
# task: get domains registrar, expiration date and current nameservers
local whois_check=$(curl -s http://w.rkutil.us/"$ROOT_DOMAIN"_quick|grep -v "Status\|Domain details\|Admin\|Created:\|Changed:")
local cant_parse=$(echo "$whois_check"|grep -o "unable to parse")
# output: formatting
echo
echo -e " CURRENT WHOIS\n$SECTION"
echo " Registration & Nameservers Only:"
# error: no records found
if [ -z "$whois_check" ]
then
echo " $(tput setaf 1)No Records Found!$(tput sgr0)"
else
# error: cannot parse returned records
if [ "$cant_parse" == "unable to parse" ]
then
echo "$(tput setaf 1)$whois_check$(tput sgr0)"|grep "Sorry, but I was unable to parse"|sed 's/^/ /'
echo " Please run a regular whois check. (ie. ~$ whois $DOMAIN)$(tput sgr0)"
else
# output: success
echo "$whois_check"|sed 's/^/ /'
fi
fi
echo
# cleanup whois data
unset ROOT_DOMAIN && unset whois_check && unset cant_parse
}
# pull any/all publicly viewable zone records
FetchVisibleZoneInfo(){
# task: get visible zone data
local zone_records=$(dig +nocmd "$DOMAIN" any +multiline +noall +answer)
local records_avail=$(echo "$zone_records"|head -1)
# output: formatting
echo
echo -e " ZONE RECORDS (has propagated)\n$SECTION"
echo " Currently Visible:"
if [ -z "$records_avail" ]
then
# error: no records found
echo " $(tput setaf 1)No Records Found!$(tput sgr0)"
else
# output: success
echo "$zone_records"|sed 's/^/ /'|grep -v ";; Truncated"
fi
echo
# cleanup visible zone data
unset records_avail && unset zone_records
}
# get where web traffic and mail go
CheckWherePoints(){
# task: get visible A and MX entries
local where_it_points=$(dig +short $DOMAIN|grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
local mx_records=$(dig +short mx "$DOMAIN"|sort -n|sed 's/^/MX: /')
local mx_entry
local mx_destination_ip
if [ -z "$mx_records" ]
then
mx_records=$(dig +short mx "$ZONE"|sort -n|sed 's/^/MX: /')
fi
unset ZONE
# error: no A or MX entries found
if [[ -z "$where_it_points" && -z "$mx_records" ]]
then
echo
echo -e " WHERE WEB TRAFFIC GOES\n$SECTION"
echo " $(tput setaf 1)No Records Found!$(tput sgr0)"
echo
echo
echo -e " WHERE MAIL TRAFFIC GOES\n$SECTION"
echo " $(tput setaf 1)No Records Found!$(tput sgr0)"
else
# task: get reverse lookup and serials of found MX records
echo
echo -e " WHERE WEB TRAFFIC GOES\n$SECTION"
echo " Active A Record(s):"
while read -r this_ip
do
local get_hostname=$(host "$this_ip"|grep "pointer"|awk {'print $5'})
for check_ptr in "$get_hostname"
do
# task: do we own this ip
local we_own_this
if $(whois "$this_ip"|grep -q "InMotion Hosting\|Web Hosting Hub")
then
we_own_this="\n\t \xe2\x86\xb3 $(tput setaf 2)Points To Us!$(tput sgr0)\n"
else
we_own_this="\n\t \xe2\x86\xb3 $(tput setaf 1)Is 3rd Party!$(tput sgr0)\n"
fi
# output: a records and reverse lookup
if [ "$(echo "$check_ptr"|grep -o "\."|wc -l)" -gt 1 ]
then
local its_ptr=$(echo "$check_ptr"|sed 's/.$//')
echo -ne "A: $this_ip [ PTR:$(tput setaf 7) $its_ptr$(tput sgr0) ]"|sed 's/^/ /';
echo -e "$we_own_this"
else
echo -ne "A: $this_ip [ $(tput setaf 1)No PTR Configured$(tput sgr0) ]"|sed 's/^/ /';
echo -e "$we_own_this"
fi
# cleanup this ip's ptr data
unset its_ptr && unset we_own_this
done
# cleanup this ip
unset get_hostname && unset check_ptr && unset this_ip
# read $where_it_points
done << EOF
$where_it_points
EOF
echo
# output: formatting
echo
echo -e " WHERE MAIL TRAFFIC GOES\n$SECTION"
echo " Active MX Record(s):"
if [ -z "$mx_records" ]
then
# error: no records found
echo " $(tput setaf 1)No Records Found!$(tput sgr0)"
else
# task: get reverse dns lookup and serials of found MX records
local mx_hostname_ips=$(echo "$mx_records"|awk {'print $3'}|sed 's/.$//'|xargs dig +short)
local mx_tmp=$(date +"%y%m%d%M%N")
echo "$mx_records"|sed 's/.$//' > /tmp/.sdig.$mx_tmp.mxhosts
echo "$mx_hostname_ips" > /tmp/.sdig.$mx_tmp.mxips
while true
do
read -r mx_entry <&3
read -r mx_destination_ip <&4
if [ -z "$mx_entry" -o -z "$mx_destination_ip" ]
then
break
fi
local this_ptr=$(host "$mx_destination_ip"|grep "pointer"|awk {'print $5'})
# task: do we own this ip
local we_own_this
if $(whois "$mx_destination_ip"|grep -q "InMotion Hosting\|Web Hosting Hub")
then
we_own_this="\n\t \xe2\x86\xb3 $(tput setaf 2)Points To Us!$(tput sgr0)\n"
else
we_own_this="\n\t \xe2\x86\xb3 $(tput setaf 1)Is 3rd Party!$(tput sgr0)\n"
fi
# output: mx data, and reverse lookup
if [ "$(echo "$this_ptr"|grep -o "\."|wc -l)" -gt 1 ]
then
local its_ptr=$(echo "$this_ptr"|sed 's/.$//')
echo -ne " $mx_entry => $mx_destination_ip [ PTR:$(tput setaf 7) $its_ptr$(tput sgr0) ]"
echo -e "$we_own_this"
else
echo -ne " $mx_entry => $mx_destination_ip [ $(tput setaf 1)No PTR Configured$(tput sgr0) ]"
echo -e "$we_own_this"
fi
# read MX data
done 3< /tmp/.sdig.$mx_tmp.mxhosts 4< /tmp/.sdig.$mx_tmp.mxips && rm -f /tmp/.sdig.$mx_tmp*
# cleanup this MX's reverse lookup and serial data
unset this_ptr && unset its_ptr && unset mx_entry && unset mx_destination_ip && unset we_own_this
fi
# cleanup this domain's MX data
unset mx_records && unset mx_hostname_ips && unset mx_tmp
fi
# cleanup this domains record's ptr and serial data
unset where_it_points
}
# check google's public dns for propagated/cached entries (if exist) + serial of each
CheckPublicDNS(){
# output publicly viewable cached dns entries
echo
echo -e " PUBLIC DNS (what presumably has propagated & been cached)\n$SECTION"
echo " Level3's Public DNS:"
echo "$(FetchARecordsAndSerial a.resolvers.level3.net)"
echo "$(FetchARecordsAndSerial b.resolvers.level3.net)"
echo "$(FetchARecordsAndSerial c.resolvers.level3.net)"
echo
echo " Google's Public DNS:"
echo "$(FetchARecordsAndSerial google-public-dns-a.google.com)"
echo "$(FetchARecordsAndSerial google-public-dns-b.google.com)"
}
# check internal ns & clusters (both brands) for entries (if exist) + serial of each
CheckInternalDNS(){
# task: set internal brands
local imh="inmotionhosting.com"
local hub="webhostinghub.com"
# output: found internal dns entries by brand
echo
echo -e " INMOTION (in house)\n$SECTION"
echo " Nameservers:"
echo " $(FetchARecordsAndSerial ns.$imh)"
echo "$(FetchARecordsAndSerial ns2.$imh)"
echo
echo " Clusters:"
echo "$(FetchARecordsAndSerial wczcluster1.$imh)"
echo "$(FetchARecordsAndSerial wczcluster2.$imh)"
echo "$(FetchARecordsAndSerial wczcluster3.$imh)"
echo "$(FetchARecordsAndSerial wczcluster4.$imh)"
echo "$(FetchARecordsAndSerial wczcluster5.$imh)"
echo
echo
echo -e " HUB (in house)\n$SECTION"
echo " Nameservers:"
echo "$(FetchARecordsAndSerial ns1.$hub)"
echo "$(FetchARecordsAndSerial ns2.$hub)"
echo
echo " Clusters:"
echo "$(FetchARecordsAndSerial echzcluster1.$hub)"
echo "$(FetchARecordsAndSerial wchzcluster2.$hub)"
echo
# cleanup internal brands
unset imh && unset hub
}
# fetch A record entries from the given DNS server...
FetchARecordsAndSerial(){
# task: get A records
local server="$1"
local a_records=$(dig +short $DOMAIN @$server|grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
# error: none found
if [ -z "$a_records" ]
then
if [ "$(echo "$server"|grep -o "\."|wc -l)" -gt 2 ]
then
echo -e "@$(echo "$server"|cut -d\. -f1,2): $(tput setaf 1)No Records Found!$(tput sgr0)\n"|sed 's/^/ /'
else
echo -e "@$(echo "$server"|cut -d\. -f1): $(tput setaf 1)No Records Found!$(tput sgr0)\n"|sed 's/^/ /'
fi
elif [ "$(echo "$a_records"|grep -o 'timed out')" == "timed out" ]
then
if [ "$(echo "$server"|grep -o "\."|wc -l)" -gt 2 ]
then
echo -e "@$(echo "$server"|cut -d\. -f1,2): $(tput setaf 1)Connection Timed Out!$(tput sgr0)\n"|sed 's/^/ /'
else
echo -e "@$(echo "$server"|cut -d\. -f1): $(tput setaf 1)Connection Timed Out!$(tput sgr0)\n"|sed 's/^/ /'
fi
else
# task: get ptr and serials of found A records
while read -r a_record
do
local this_ptr=$(host "$a_record"|grep "pointer"|awk {'print $5'})
local this_serial=$(dig "$DOMAIN" @"$server" +nocmd any +multiline +noall +answer|grep -h serial|awk {'print $1'})
if [ "$(echo "$this_serial"|wc -m)" -lt 10 ]
then
# error: serial cannot be found?
this_serial="$(tput setaf 1)The serial cannot be determined.$(tput sgr0)"
else
# output: success
this_serial="$(tput setaf 3)Serial: $this_serial$(tput sgr0)"
fi
# output: formatting
if [ "$(echo "$this_ptr"|grep -o "\."|wc -l)" -gt 1 ]
then
if [ "$(echo "$server"|grep -o "\."|wc -l)" -gt 2 ]
then
echo -e "@$(echo "$server"|cut -d\. -f1,2): $a_record [ PTR:$(tput setaf 7) $(echo "$this_ptr"|sed 's/.$//')$(tput sgr0) ] \n\t \xe2\x86\xb3 $this_serial\n"|sed 's/^/ /'
else
echo -e "@$(echo "$server"|cut -d\. -f1): $a_record [ PTR:$(tput setaf 7) $(echo "$this_ptr"|sed 's/.$//')$(tput sgr0) ] \n\t \xe2\x86\xb3 $this_serial\n"|sed 's/^/ /'
fi
else
if [ "$(echo "$server"|grep -o "\."|wc -l)" -gt 2 ]
then
echo -e "@$(echo "$server"|cut -d\. -f1,2): $a_record [ $(tput setaf 1)No PTR Configured$(tput sgr0) ] \n\t \xe2\x86\xb3 $this_serial\n"|sed 's/^/ /'
else
echo -e "@$(echo "$server"|cut -d\. -f1): $a_record [ $(tput setaf 1)No PTR Configured$(tput sgr0) ] \n\t \xe2\x86\xb3 $this_serial\n"|sed 's/^/ /'
fi
fi
# cleanup this A record's ptr and serial data
unset this_serial && unset this_ptr && unset a_record
# read $a_records
done << EOF
$a_records
EOF
unset a_records
fi
}
# dig it all up
Supadig(){
# output: instructions while in less
echo
# removed: Supadig|less -R (piping to less seems to confuse people ??? wow):
# echo " Hey!"
# echo -e " \xe2\x86\xb3 Arrow keys to scroll"
# echo " Press q to quit"
# echo " Press h for more options"
DisplayHeader
# output: results of all dns data
echo
CheckIsRootDomain
echo
FetchWhois
echo
FetchVisibleZoneInfo
echo
CheckPublicDNS
echo
CheckWherePoints
echo
CheckInternalDNS
echo
# final cleanup
unset DOMAIN
unset SECTION
}
#
# check input, validate and die on error [else] Supadig
#
# check for false input and display help
if [[ -z "$1" || "$1" == "--help" ]]
then
# output: usage
DisplayHeader && DisplayUsage
exit 0
# display info
elif [ "$1" == "--about" ]
then
# output: about/usage
DisplayHeader && DisplayInfo && DisplayUsage
exit 0
else
# user seems to not need help, but lets double check
if [[ -n "$2" || "$(echo "$*"|grep -o "\."|wc -l)" == 0 || -z "$(echo "$*"|cut -d\. -f1)" ]]
then
# error: entry appears invalid
DisplayHeader && echo -e "$(tput setaf 1)\n ERROR!$(tput sgr0) \"$*\" is an invalid entry!" && DisplayUsage
exit 1
else
# ok, input seems valid, but has an actual valid domain/tld been given?
validated=$(echo "$*"|sed 's/http:\/\///'|sed 's/https:\/\///'|sed 's/ftp:\/\///'|sed 's/ftpes:\/\///'|cut -d@ -f2-|cut -d\/ -f1)
confirm_tld=$(echo "$validated"|rev|cut -d\. -f1 -s|rev)
declare -a valid_tlds=("ac" "ad" "ae" "aero" "af" "ag" "ai" "al" "am" "an" "ao" "aq" "ar" "arpa" "as" "asia" "at" "au" "aw" "ax"
"az" "ba" "bb" "bd" "be" "bf" "bg" "bh" "bi" "biz" "bj" "bl" "bm" "bn" "bo" "br" "bs" "bt" "bv" "bw" "by" "bz" "ca" "cat" "cc"
"cd" "cf" "cg" "ch" "ci" "ck" "cl" "cm" "cn" "co" "com" "coop" "cr" "cu" "cv" "cx" "cy" "cz" "de" "dj" "dk" "dm" "do" "dz" "ec"
"edu" "ee" "eg" "eh" "er" "es" "et" "eu" "fi" "fj" "fk" "fm" "fo" "fr" "ga" "gb" "gd" "ge" "gf" "gg" "gh" "gi" "gl" "gm" "gn" "gov"
"gp" "gq" "gr" "gs" "gt" "gu" "gw" "gy" "hk" "hm" "hn" "hr" "ht" "hu" "id" "ie" "il" "im" "in" "info" "int" "io" "iq" "ir" "is" "it"
"je" "jm" "jo" "jobs" "jp" "ke" "kg" "kh" "ki" "km" "kn" "kp" "kr" "kw" "ky" "kz" "la" "lb" "lc" "li" "lk" "lr" "ls" "lt" "lu" "lv"
"ly" "ma" "mc" "md" "me" "mf" "mg" "mh" "mil" "mk" "ml" "mm" "mn" "mo" "mobi" "mp" "mq" "mr" "ms" "mt" "mu" "museum" "mv" "mw" "mx"
"my" "mz" "na" "name" "nc" "ne" "net" "nf" "ng" "ni" "nl" "no" "np" "nr" "nu" "nz" "om" "org" "pa" "pe" "pf" "pg" "ph" "pk" "pl" "pm"
"pn" "pr" "pro" "ps" "pt" "pw" "py" "qa" "re" "ro" "rs" "ru" "rw" "sa" "sb" "sc" "sd" "se" "sg" "sh" "si" "sj" "sk" "sl" "sm" "sn"
"so" "sr" "st" "su" "sv" "sy" "sz" "tc" "td" "tel" "tf" "tg" "th" "tj" "tk" "tl" "tm" "tn" "to" "tp" "tr" "travel" "tt" "tv" "tw"
"tz" "ua" "ug" "uk" "um" "us" "uy" "uz" "va" "vc" "ve" "vg" "vi" "vn" "vu" "wf" "ws" "ye" "yt" "yu" "za" "zm" "zw")
# task: validate given domain entry
for valid_tld in "${valid_tlds[@]}"
do
if [ "$confirm_tld" == "$valid_tld" ]
then
DOMAIN=$(echo "$validated")
# cleanup tld validation
unset valid_tld && unset valid_tlds && unset confirm_tld && unset validated
# task: supadig the domain
Supadig
# removed: Supadig|less -R (piping to less seems to confuse people ??? wow)
exit 0
fi
done
# error: domain appears invalid
DisplayHeader && echo -e "\n $(tput setaf 1)ERROR!$(tput sgr0) \"$*\" is an invalid domain!" && DisplayUsage
exit 1
fi
fi
# eof
Zerion Mini Shell 1.0