Dans mon précédent article sur la mise en place de dnssec, je vous avais renvoyé pour la partie supervision de l'expiration des enregistrements dnssec sur un article de Stéphane Bortzmeyer expliquant comment le mettre en place sous icinga.
Comme tout le monde n'a pas icinga sous la main, voici un petit script de ma composition qui vous enverra un mail lorsqu'un enregistrement RRSIG arrive à expiration (et donc que quelque chose s'est mal passé dans la resignature automatique par bind)
#!/bin/bash
### CONFIGURATION DEFAULTS ###
# Warn if an RRSIG expires in less than this time period
WARN_TIME="4 weeks"
# print warnings to STDOUT (true or false)
WARN_STDOUT=false
# Send warnings by mail (true or false)
WARN_MAIL=true
# Where to send mail alerts (if WARN_MAIL set to true)
SEND_WARNING_MAIL_TO="hostmaster@example.tld"
SEND_WARNING_MAIL_FROM="hostmaster@example.tld"
# Command to get zone list. Adapt to your settings.
ZONE_LIST_COMMAND="ls /etc/bind/keys"
# Signed zone file path for zone ${zone}
# Use single quotes to avoid variable expansion
ZONE_FILE_PATH='/etc/bind/zones/db.${zone}.signed'
### DO NOT MODIFY ANYTHING BELOW UNLESS YOU EXACTLY KNOW WHAT YOU ARE DOING ###
# Usage function
function usage {
echo "USAGE: $(basename $0) [-h] [-d] [-e <warning_time>] [-m] [-f <sender>] [-t <destination>] [-s] [-q]"
echo ""
echo "Options:"
echo " -h, --help print usage message and exit"
echo " -d, --debug debug mode, show expiration date of older RRSIG record for each domain even if not in"
echo " warning time period (only on STDOUT)"
echo " -e <time>, warn if RRSIG expires in the given time period"
echo " --expirein <time>"
echo " -m, --mail send warning by mail"
echo " -f <sender>, set warning mail sender address"
echo " --from <sender>"
echo " -t <dest>, set warning mail destination address"
echo " --to <dest>"
echo " --nomail do NOT send warning by mail even if enabled by default"
echo " -s, --stdout show warnings on stdout"
echo " -q, --quiet do NOT show warnings on stdout, even if enabled by default"
echo ""
}
DEBUG=false
# Options parsing
PARSED_OPTIONS=$(getopt -n "$0" -o hde:msqf:t: --long "help,debug,expirein:,mail,stdout,quiet,from:,to:,nomail,nostdout" -- "$@")
if [ $? -ne 0 ];
then
echo "" >&2
usage >&2
exit 1
fi
eval set -- "$PARSED_OPTIONS"
while true; do
case "$1" in
-h|--help)
usage >&2
exit 1
;;
-d|--debug)
DEBUG=true
shift
;;
-e|--expirein)
case "$2" in
"") shift 2 ;;
*) WARN_TIME=$2 ; shift 2;;
esac
;;
-m|--mail)
WARN_MAIL=true
shift
;;
-f|--from)
case "$2" in
"") shift 2 ;;
*) SEND_WARNING_MAIL_FROM=$2 ; shift 2;;
esac
;;
-t|--to)
case "$2" in
"") shift 2 ;;
*) SEND_WARNING_MAIL_TO=$2 ; shift 2;;
esac
;;
--nomail)
WARN_MAIL=false
shift
;;
-s|--stdout)
WARN_STDOUT=true
shift
;;
-q|--quiet|--nostdout)
WARN_STDOUT=false
shift
;;
--)
shift
break
;;
esac
done
# Warn time limit since epoch
WARN_EPOCH=$(date --date "+${WARN_TIME}" +"%s")
# For each zone
for zone in $( $ZONE_LIST_COMMAND ); do
# Get expiration time of next expiring RRSIG
N=$(named-compilezone -q -D -f raw -o - ${zone} $(eval echo ${ZONE_FILE_PATH}) | grep "IN RRSIG" |awk '{ print $9 }' |sort -n |head -1)
# Transform to epoch (usefull for date comparison)
EXP_EPOCH=$(date --date "${N:4:2}/${N:6:2}/${N:0:4} ${N:8:2}:${N:10:2}:${N:12:2}" +"%s")
EXP_HUMANREADABLE=$(LANG=C date --date "${N:4:2}/${N:6:2}/${N:0:4} ${N:8:2}:${N:10:2}:${N:12:2}")
# Warn if in expiration warning time
if [ ${EXP_EPOCH} -le ${WARN_EPOCH} ]; then
WARN_MSG="\
DNSSEC EXPIRATION WARNING
-------------------------
Domain ${zone} has an RRSIG expiring in less than ${WARN_TIME}
Next expiration date on (${EXP_EPOCH}) ${EXP_HUMANREADABLE}
"
$WARN_STDOUT && echo -e "${WARN_MSG}"
if $WARN_MAIL; then
WARN_MAIL_HEADERS="\
From: ${SEND_WARNING_MAIL_FROM}
To: <${SEND_WARNING_MAIL_TO}>
Subject: ***DNSSEC RRSIG EXPIRATION WARNING ***
Date: $(date -R)
"
echo -e "${WARN_MAIL_HEADERS}\n${WARN_MSG}" | sendmail -t -oi -f "${SEND_WARNING_MAIL_FROM}"
fi
else
$DEBUG && echo "Next Expiration of zone ${zone} (no warning) on (${EXP_EPOCH}) ${EXP_HUMANREADABLE}"
fi
done
exit 0
Tout ce que vous avez à faire, c'est de déposer ce scripts dans /etc/cron.daily
(n'oubliez pas de le rendre exécutable) et adapter les valeurs par défaut en début de script et hop, vous recevrez un mail 3 jours avant l'expiration des enregistrements RRSIG.
La variable WARN_TIME
contient la période de temps dans laquelle la présence de l'expiration d'un enregistrement RRSIG provoque une alarme. C'est une "date string" compréhensible par la commande date. Par exemple, 3 days provoquera une alarme si un enregistrement RRSIG arrive a expiration dans les 3 prochains jours. On peut également utiliser "Next thursday" pour les domaines dont un enregistrement RRSIG arrive a expiration avant jeudi prochain, ou bien "next month".
Les variables WARN_STDOUT
et WARN_MAIL
servent respectivement à afficher les warning sur la sortie standard ou à les envoyer par mail.
Les variables SEND_WARNING_MAIL_TO
et SEND_WARNING_MAIL_FROM
servent à définir respectivement le(s) destinataire(s) et l'expéditeur (d'en-tête et d'enveloppe) du mail d'alarme.
La variable ZONE_LIST_COMMAND
indique au script comment obtenir la liste des domaines à checker. Pour mon cas, chaque domaine a ses clés dans un sous-répertoire spécifique de /etc/bind/keys dont le nom est le nom du domaine. Ainsi, je me contente de lister le contenu de /etc/bind/keys. Toute autre commande qui fournit la liste des domaines à vérifier fera l'affaire. Au pire, le cat d'un fichier texte.
Enfin, la variable ZONE_FILE_PATH
indique le chemin du fichier de zone signé pour la zone ${zone}
. Pensez à utiliser des simples quotes pour éviter l'expansion de la variable ${zone}
.
J'ai préféré baser ce script sur le contenu des fichiers de zone signés plutôt que sur une interrogation du DNS.
Vous pouvez aussi l'appeler manuellement avec les options qui vont bien :
USAGE: dnssec-monitor [-h] [-d] [-e <warning_time>] [-m] [-f <sender>] [-t <destination>] [-s] [-q]
Options:
-h, --help print usage message and exit
-d, --debug debug mode, show expiration date of older RRSIG record for each domain even if not in
warning time period (only on STDOUT)
-e <time>, warn if RRSIG expires in the given time period
--expirein <time>
-m, --mail send warning by mail
-f <sender>, set warning mail sender address
--from <sender>
-t <dest>, set warning mail destination address
--to <dest>
--nomail do NOT send warning by mail even if enabled by default
-s, --stdout show warnings on stdout
-q, --quiet do NOT show warnings on stdout, even if enabled by default
Par exemple, pour afficher le résultat sur la sortie standard, ne pas envoyer de mail, alarmer s'il y a une expiration dans les 16 prochains jours, et afficher les prochaines dates d'expiration pour chaque domaine même s'il n'y a pas d'expiration dans la période indiquée :
$ ./dnssec-monitor --nomail -s -e "16 days" -d
Next Expiration of zone example.tld (no warning) on (1404131654) Mon Jun 30 14:34:14 CEST 2014
Next Expiration of zone example2.tld (no warning) on (1404130965) Mon Jun 30 14:22:45 CEST 2014
Next Expiration of zone example3.tld (no warning) on (1404133571) Mon Jun 30 15:06:11 CEST 2014
DNSSEC EXPIRATION WARNING
-------------------------
Domain example4.tld has an RRSIG expiring in less than 16 days
Next expiration date on (1403990327) Sat Jun 28 23:18:47 CEST 2014
Comments
comments powered by Disqus