Проверяем корректно ли работает домен. Чекаем serial, ptr, dns propagation, status, current ns, ttl сразу одним махом. Когда работаешь в хостинге, и каждый день проверять по 1-20 доменов, скрипт сильно оптимизирует рабочее время.
#!/bin/bash
if [ -z $1 ]; then
echo -e "Usage:\n\t$0 <domain>\n\t <ip>"
exit 0
else
domain=$1
fi
pattern=( "[nN]server:" "Name Server:" "\[Name Server\]" "nameservers:" ) # угадываем как записаны NS в whois-треше
HOST_WAIT="2" # timeout in sec
: ${WHOIS="/usr/bin/whois"}
CL_dark="\e[38;5;242m"
CL_ok="\e[38;5;2m"
CL_clientTransferProhibited="\e[38;5;13m"
CL_linked="\e[38;5;64m"
CL_epp_codes="\e[38;5;117m"
CL_orange="\e[38;5;166m"
CL_mnt="\e[38;5;31m"
CL_status="\e[38;5;30m"
CL_ptr="\e[38;5;26m"
CL_down="\e[38;5;124m"
CL_bad_ptr="\e[38;5;125m"
CL_good_ptr="\e[38;5;11m"
CL_arec="\e[38;5;26m"
CL_txt="\e[38;5;241m"
CL_hold="\e[38;5;124m"
CL_close="\e[0m"
valid_ip () {
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
IFS='.'; ip=($ip); unset IFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}
bl_ch () {
local ip="$1"
echo -e "\n ${CL_txt} Blacklist check: ${CL_close}"
BLISTS="
dnsbl.httpbl.org
cbl.abuseat.org
dnsbl.sorbs.net
bl.spamcop.net
zen.spamhaus.org
combined.njabl.org
"
# register at
http://www.projecthoneypot.org/httpbl_api.php to
# obtain an API-key
HTTPbl_API_KEY="[api_key]"
ERROR() {
echo $0 ERROR: $ip >&2
exit 2
}
[ $# -ne 1 ] && ERROR 'Please specify a single IP address'
reverse=$( echo "${ip}" | sed -r 's/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/\4.\3.\2.\1/g' )
if [ "x${reverse}" = "x" ] ; then
ERROR "IMHO '$ip' doesn't look like a valid IP address"
exit 1
fi
for BL in ${BLISTS} ; do
if [ "$BL" == "dnsbl.httpbl.org" ]; then
LISTED="$( dig +short -t a ${HTTPbl_API_KEY}.${reverse}.${BL}. )"
printf "${CL_mnt}${HTTPbl_API_KEY}.${CL_txt}%-40s${CL_dark}%-20s${CL_close}\n" "${reverse}.${BL}." ${LISTED:----}
else
LISTED="$( dig +short -t a ${reverse}.${BL}. )"
printf "${CL_txt}%-50s${CL_dark}%-20s${CL_close}\n" ${reverse}.${BL}. ${LISTED:----}
fi
done
}
get_arpa () {
if valid_ip ${domain}; then
echo -e "${CL_txt} NS's \t\t [ PTR ] ${CL_close}"
NS=( $( V="$(host -W $HOST_WAIT -a ${domain}
if [ $? -eq 1 ]; then
echo -e "${CL_txt}> ${CL_down}NXDOMAIN ${CL_close}" 1>&2
fi
)"
V_FILTERED="$(echo "${V}" | grep "IN.*NS" | awk '{print $5}')"
if [ -z "${V_FILTERED}" ]; then
echo -e "${CL_txt}> ${CL_orange}no NS ${CL_close}" 1>&2
fi
echo "${V_FILTERED}"
)
)
for ns in ${NS[@]}; do
recPTR="$( host -W $HOST_WAIT -tPTR "${domain}" "${ns}" 2>/dev/null | awk -F"name pointer" '{print $2}' | grep . | tr -d " " | tr "\n" " " )"
printf "${CL_orange}%-30s${CL_PTR}%-35s${CL_close}\n" "${ns}" "${recPTR}"
done
RET=0
fi
return ${RET:-1}
}
get_whois () {
# ищем в whois нужное, и пишем это в переменные
WHOIS_V=$( ${WHOIS} ${domain:-NONEXISTSDOMAIN.COM} )
for p in "${pattern[@]}"; do
NS=( $(echo "${WHOIS_V}" | grep "${p}" | \
sed "s/$p//" | \
awk '{print $1}' | \
tr "[A-Z]" "[a-z]" | \
sort | uniq
)
)
[[ ! -z "${NS}" ]] && break # если по паттерну нашли строку с NS, дальше не грепаем
done
[[ ${#NS[@]} -eq 0 ]] && { echo -e "${CL_down}${WHOIS_V}\n${CL_close}"; exit 0; } # если, по паттерну, ничего не нашли
mntby=$( echo "${WHOIS_V}" | grep -i "mnt-by:" | head -n1 | tr -s ' ' )
#
https://www.icann.org/resources/pages/epp-s...s-2014-06-16-en status=( $( echo "${WHOIS_V}" | \
grep -iEo "status:.*" | \
sed 's/[Ss]tatus://' | \
sed 's/http[^ ]*//g' | \
tr -d " " | \
sed "s|linked|\\${CL_linked}linked\\${CL_close}| ; \
s|addPeriod|\\${CL_epp_codes}addPeriod\\${CL_close}| ; \
s|autoRenewPeriod|\\${CL_epp_codes}autoRenewPeriod\\${CL_close}| ; \
s|inactive|\\${CL_epp_codes}inactive\\${CL_close}| ; \
s|[oO][kK]|\\${CL_ok}ok\\${CL_close}| ; \
s|pendingCreate|\\${CL_epp_codes}pendingCreate\\${CL_close}| ; \
s|pendingDelete|\\${CL_epp_codes}pendingDelete\\${CL_close}| ; \
s|pendingRenew|\\${CL_epp_codes}pendingRenew\\${CL_close}| ; \
s|pendingRestore|\\${CL_epp_codes}pendingRestore\\${CL_close}| ; \
s|pendingTransfer|\\${CL_epp_codes}pendingTransfer\\${CL_close}| ; \
s|pendingUpdate|\\${CL_epp_codes}pendingUpdate\\${CL_close}| ; \
s|redemptionPeriod|\\${CL_epp_codes}redemptionPeriod\\${CL_close}| ; \
s|renewPeriod|\\${CL_epp_codes}renewPeriod\\${CL_close}| ; \
s|serverDeleteProhibited|\\${CL_epp_codes}serverDeleteProhibited\\${CL_close}| ; \
s|serverHold|\\${CL_epp_codes}serverHold\\${CL_close}| ; \
s|serverRenewProhibited|\\${CL_epp_codes}serverRenewProhibited\\${CL_close}| ; \
s|serverTransferProhibited|\\${CL_epp_codes}serverTransferProhibited\\${CL_close}| ; \
s|serverUpdateProhibited|\\${CL_epp_codes}serverUpdateProhibited\\${CL_close}| ; \
s|transferPeriod|\\${CL_epp_codes}transferPeriod\\${CL_close}| ; \
s|clientDeleteProhibited|\\${CL_epp_codes}clientDeleteProhibited\\${CL_close}| ; \
s|clientHold|\\${CL_hold}clientHold\\${CL_close}| ; \
s|clientRenewProhibited|\\${CL_epp_codes}clientRenewProhibited\\${CL_close}| ; \
s|clientTransferProhibited|\\${CL_clientTransferProhibited}clientTransferProhibited\\${CL_close}| ; \
s|clientUpdateProhibited|\\${CL_epp_codes}clientUpdateProhibited\\${CL_close}|
"
)
)
# Итого, вынесли с whois переменные $mntby $status ${NS[]}
}
print_line () {
local i=$1
# для первой строки, свой принт
if [ $i -eq 0 ]; then
printf "${CL_orange}%-30s${CL_recAs}%-16s${CL_PTR}%-35s${CL_rDNS_CHK}%-8s${CL_dark}%-20s${CL_close}\n" "${ns}" "${recAs}" "${PTR}" "${rDNS_CHK}" "${rDNS_CHK_TXT}"
else
printf " ${CL_recAs}%-16s${CL_PTR}%-35s${CL_rDNS_CHK}%-8s${CL_dark}%-20s${CL_close}\n" "${recAs}" "${PTR}" "${rDNS_CHK}" "${rDNS_CHK_TXT}"
fi
}
get_ns () {
local NStype=$1
case ${NStype} in
auth)
:
NS_save_auth=( "${NS[@]}" )
;;
locall)
NS=()
NS=( $(cat /etc/resolv.conf | grep nameserver | grep -oE "[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}" ) )
NS_save_locall=( "${NS[@]}" )
;;
public)
NS=()
NS=( 8.8.8.8 8.8.4.4 1.1.1.1 9.9.9.9 5.1.2.1 5.1.2.2)
NS_save_public=( "${NS[@]}" )
;;
*)
NS=()
echo "bad NS type"
exit 0
;;
esac
local ns_seq=0
for ns in ${NS[@]}; do
# flush var's
recAs=""
PTR=""
rDNS_CHK=""
rDNS_CHK_TXT=""
CL_PTR=""
CL_recAs=""
CL_rDNS_CHK=""
serial=""
# строим список А-записей одной строкой через пробелы
recA="$( host -W $HOST_WAIT -tA "${domain}" "${ns}" 2>/dev/null | awk -F"has address" '{print $2}' | grep . | tr -d " " | tr "\n" " " )"
#echo "a:${recA}:"
# для функции print_line
local i=0
if [[ -z "${recA}" ]]; then
recAs="-"
PTR="-"
rDNS_CHK="-"
CL_PTR="${CL_dark}"
CL_recAs="${CL_dark}"
CL_rDNS_CHK="${CL_dark}"
print_line $i
else
CL_recAs="${CL_arec}"
for recAs in ${recA}; do
PTR="$( host -W $HOST_WAIT "${recAs}" "${ns}" 2>/dev/null | grep -v "not found:" | awk -F"name pointer" '{print $2}' | grep . | tr "\n" " " | tr -d " " )"
#echo "ptr:${PTR}:"
if [[ -z "${PTR}" ]]; then
PTR="-"
#LN_PTR="17"
CL_PTR="${CL_dark}"
rDNS_CHK="-"
rDNS_CHK_TXT=""
CL_rDNS_CHK="${CL_dark}"
else
CL_PTR="${CL_ptr}"
#LN_PTR=$(( ${#PTR} +8 ))
rDNS="$( host -W $HOST_WAIT "${PTR}" "${ns}" 2>/dev/null | grep -v "not found:" | awk -F"has address" '{print $2}' | grep . | tr -d " " | tr "\n" " " )"
#echo "rdns:${rDNS}:"
# сверяем А-запись и резолв PTR
if [[ "${rDNS}" == *${recAs}* ]]; then
rDNS_CHK="[ GOOD ]"
rDNS_CHK_TXT=""
CL_rDNS_CHK="${CL_good_ptr}"
else
rDNS_CHK="[ BAD ]"
rDNS_CHK_TXT="${rDNS:-NULL}"
CL_rDNS_CHK="${CL_bad_ptr}"
fi
fi
print_line $i
(( i++ ))
done
fi
# достаем с текущего ${ns} сериал для домена ${domain}
local SOA="$( host -W $HOST_WAIT -tSOA "${domain}" "${ns}" 2>/dev/null | awk -F"has SOA record" '{print $2}' | grep . )"
local SOAmaster="$( echo "${SOA}" | awk '{print $1}' )"
local SOAserial="$( echo "${SOA}" | awk '{print $3}' | grep -Eo "[0-9]{10}" | tr -d " " )"
local SOAttl="$( echo "${SOA}" | awk '{$1=$2=$3="";print}' )"
case ${NStype} in
auth) recS_auth[$ns_seq]="${SOAserial}"
recS_auth_master[$ns_seq]="${SOAmaster}"
recS_auth_ttl[$ns_seq]="${SOAttl}"
;;
locall) recS_locall[$ns_seq]="${SOAserial}"
;;
public) recS_public[$ns_seq]="${SOAserial}"
;;
esac
(( ns_seq++ ))
done
}
serial_check_auth () {
master_ok=0
# совпадает ли мастер сервер в ответах от авторитативных серверов
find_master=( $( echo "${recS_auth_master[@]}" | tr " " "\n" | sort | uniq | grep . ) )
if [ ! ${#find_master[@]} -eq 1 ]; then
echo -e "\t ${CL_down}SOA master mismatch in Authoritative DNS: ${find_master[@]:-"N/A"}${CL_close}"
else
# for start print_timers()
master_ok=1
#
echo -e "\t ${CL_txt}Find master: ${CL_ok}${find_master}${CL_close}"
# определить кто из авторитативных есть мастер; нужно ли ?
#try_resolve="$( host -W $HOST_WAIT -tA "${find_master}" "${find_master}" 2>/dev/null | grep -v "not found:" | awk -F"has address" '{print $2}' | grep . | tr -d " " | tr "\n" " " )"
# совпадает ли сериал в ответах от авторитативных серверов
find_serial=( $( echo "${recS_auth[@]}" | tr " " "\n" | sort | uniq | grep . ) )
if [ ! ${#find_serial[@]} -eq 1 ]; then
echo -e "\t ${CL_down}SOA serial mismatch in Authoritative DNS: ${find_serial[@]:-"N/A"}${CL_close}"
# global var ${CL_serial_over}
CL_serial_over="${CL_down}"
else
echo -e "\t ${CL_txt}Find serial: ${CL_ok}${find_serial}${CL_close}"
fi
fi
}
serial_check_locall () {
for ((s=0; s<${#NS_save_locall[@]}; s++)); do
if [ -z "${recS_locall[$s]}" ]; then
local CL_serial_over="${CL_dark}"
recS_locall[$s]="-"
else
if [[ "${find_serial}" =~ "${recS_locall[$s]}" ]]; then
CL_serial="${CL_ok}"
else
CL_serial="${CL_down}"
fi
fi
printf "${CL_orange}%-21s${CL_close} ${CL_serial}${CL_serial_over}%-30s${CL_close}\n" "${NS_save_locall[$s]}" "${recS_locall[$s]}"
done
}
serial_check_public () {
for ((s=0; s<${#NS_save_public[@]}; s++)); do
if [ -z "${recS_public[$s]}" ]; then
local CL_serial_over="${CL_dark}"
recS_public[$s]="-"
else
if [[ "${find_serial}" =~ "${recS_public[$s]}" ]]; then
CL_serial="${CL_ok}"
else
CL_serial="${CL_down}"
fi
fi
printf "${CL_orange}%-21s${CL_close} ${CL_serial}${CL_serial_over}%-30s${CL_close}\n" "${NS_save_public[$s]}" "${recS_public[$s]:--}"
done
}
print_timers () {
# From Pingdom:
http://dnscheck.pingdom.com/# SOA TTL recommended >= 3600.
# SOA refresh recommended >= 14400.
# SOA retry recommended >= 3600.
# SOA expire recommended >= 604800.
# SOA minimum recommended between 300 and 86400.
TIMERS=( $( for (( t=0; t<${#recS_auth_ttl[@]}; t++ )); do
echo "${recS_auth_ttl[t]}"
done | sort | uniq
)
)
if [ ! ${#TIMERS[@]} -eq 4 ]; then
echo -e "\t${CL_down} ERROR IN SOA TIMERS: ${TIMERS[@]:-"NULL"} ${CL_close}"
else
REM_RF="planned zone re-read (recommended >= 14400)"
REM_RT="how offten re-read if fail master (recommended >= 3600)"
REM_EX="how long alive after fail master (recommended >= 604800)"
REM_DF="for application (recommended between 300 and 86400)"
printf "\t ${CL_txt}Refresh: ${CL_ok}%-10s${CL_txt}%-50s${CL_close}\n" "${TIMERS[0]}" "${REM_RF}"
printf "\t ${CL_txt}Retry: ${CL_ok}%-10s${CL_txt}%-50s${CL_close}\n" "${TIMERS[1]}" "${REM_RT}"
printf "\t ${CL_txt}Expire: ${CL_ok}%-10s${CL_txt}%-50s${CL_close}\n" "${TIMERS[2]}" "${REM_EX}"
printf "\t ${CL_txt}Default TTL: ${CL_ok}%-10s${CL_txt}%-50s${CL_close}\n" "${TIMERS[3]}" "${REM_DF}"
fi
}
smtp_ssl_check () {
if [ $master_ok -eq 1 ]; then
SSL_if_support="$( openssl x509 xxx 2>&1 | grep -o "\-checkhost" )"
if [ -z "$SSL_if_support" ]; then
echo -e "${CL_txt}openssl '-checkhost' not support${CL_close}"
return 1
fi
recMX="$( host -W $HOST_WAIT -tMX "${domain}" "${find_master}" 2>/dev/null | awk -F"handled by" '{print $2}' | grep . )"
if [ -z "${recMX}" ]; then
echo "No MX-record"
return 0
fi
MX_value=( $( echo "${recMX}" | awk '{print $2}' | sed 's/\.$//' ) )
MX_prior=( $( echo "${recMX}" | awk '{print $1}' ) )
for ((m=0;m<${#MX_value[@]};m++)); do
#CL_ssl_res=""
SSL_check=""
SSL_proto=""
#RES=""
SSL_check="$( echo | openssl s_client -connect ${MX_value[m]}:25 -starttls smtp 2>&1 | openssl x509 -noout -checkhost ${MX_value[m]} 2>&1 )"
SSL_proto="$( echo | openssl s_client -connect ${MX_value[m]}:25 -starttls smtp 2>&1 | grep Protocol | sed 's/Protocol//' | sed "s/://" | tr -d " " )"
if [[ "${SSL_check}" =~ "unable to load certificate" ]]; then
CL_ssl_res="${CL_dark}"
RES="-"
SSL_proto="${SSL_proto:--}"
elif [[ "${SSL_check}" =~ "does match" ]]; then
CL_ssl_res="${CL_ok}"
RES="Ok"
else
CL_ssl_res="${CL_down}"
RES="mismatch"
fi
MX_prior[m]="[${MX_prior[m]}]"
printf "${CL_orange}%-25s ${CL_dark}%-5s${CL_ssl_res}%-10s%-10s${CL_close}\n" "${MX_value[m]}" "${MX_prior[m]}" "${RES}" "${SSL_proto}"
done
fi
}
# ----------------------- GO RUN ------------------------------------------------------
if get_arpa; then
bl_ch ${domain}
exit 0
fi
get_whois
echo -e "\n ${CL_txt} Authoritative DNS: ${CL_close}"
echo -e " ${CL_txt}${mntby:-mnt-by:}${CL_close}"
echo -e " ${CL_txt}status: ${status[@]:-"n/a"}${CL_close}\n"
echo -e "${CL_txt} NS's \t\t [ A ] [ PTR ] [ rDNS ] ${CL_close}"
get_ns auth
echo -e "\n ${CL_txt} Local DNS (TopNET): ${CL_close}"
get_ns locall
echo -e "\n ${CL_txt} Public DNS (Google, CF, DG Anycast): ${CL_close}"
get_ns public
echo -en "\n ${CL_txt} Compare SOA from authoritative DNS: ${CL_close}\n"
serial_check_auth
serial_check_locall
serial_check_public
print_timers
echo -en "\n ${CL_txt} Check SMTP SSL: ${CL_close}\n"
smtp_ssl_check
echo
exit 0