I'm attempting to clean up some large zone files and want to ensure that
none of the changes will break DNS when I implement it. Later, I'd like
to use it to verify that the records point to active hosts, but that's
later.
I started putting together a bash script, but I'm having issues where a
record exists on multiple lines. For example:
$ORIGIN example.com.
www A 10.1.2.3
A 10.1.2.4
A 10.1.2.5
...
Or where a record is delegated to a secondary name server (GSLB):
$ORIGIN example.com.
www NS gss1.example.com.
NS gss2.example.com.
Below is my kludge of a script for reference. It works (somewhat) for
single line CNAME and A records, but errors abound.
Brian
=====
BEGIN
=====
#!/bin/bash
if [[ -z $1 ]]
then echo -n "Please enter a file name (full path) : "
read FILE
else FILE=$1
fi
DOM=`echo $FILE | awk -F\/ '{print $NF}' | sed 's/db\.//g'`
cat ${FILE} |
egrep -v "^\;|^$|TXT" |
while read LINE
do LINE=(${LINE})
if [[ ${LINE[0]} == "\$ORIGIN" ]]
then ORIGIN=${LINE[1]}
[[ ${ORIGIN} == "." ]] && ORIGIN=${DOM}
else CNT=0
while [[ ${CNT} -le ${#LINE[*]} ]]
do if [[ ${LINE[$CNT]} == "A" ]] || [[
${LINE[$CNT]} == "CNAME" ]]
then HOST=${LINE[0]}
: ${LINE[*]}
ADDRESS=$_
# Random number between 6-9 to
select DNS server to query
GW=$[ ( $RANDOM % 4 ) + 6 ]
QUERY=`host ${HOST}.${ORIGIN}
10.1.2.${GW} | egrep "has address|an alias"`
: ${QUERY[*]}
RESPONSE=$_
[[ ${ADDRESS} != ${REPONSE} ]]
&& echo ${HOST}.${ORIGIN},${LINE[$CNT]},${ADDRESS},${RESPONSE}
break
fi
((CNT=$CNT+1))
done
fi
done
===
END
===
> Does anyone know of an existing script or program that can parse a zone
> file and verify records against an active server?
Have you looked at named-checkzone?
Tony.
--
f.anthony.n.finch <d...@dotat.at> http://dotat.at/
FORTIES: NORTH 5 OR 6, DECREASING 3 OR 4. MODERATE OR ROUGH. SHOWERS. GOOD.
> Does anyone know of an existing script or program that can parse a zone
> file and verify records against an active server?
named-checkzone these days does some checks unless specified not to do so.
(note to self: dont do that on a 2.5M record zone)
If you want to verify if the contents of the "current" zone and your new
zone file still match, you prob want some kind of "diff". Perhaps load
the new zone on a spare server, and do an AXFR of both zones, with some
sort/uniq/sed processing?
Paul
Oh, a challenge. Thanks
> I'm attempting to clean up some large zone files and want to ensure that
> none of the changes will break DNS when I implement it. Later, I'd like
> to use it to verify that the records point to active hosts, but that's
> later.
>
> I started putting together a bash script, but I'm having issues where a
> record exists on multiple lines. For example:
Since, in a zone file, any line that begins with white space (tab or space
character) will use the same left hand side name as the previous line. So,
using AWK, you could do something like:
awk 'BEGIN{LHS=""}/^[WS]/{print LHS,$0;next}{print $0;LHS=$1}'
(Guaranteed NOT to work without lots of tweeks and testing. Use at your
own risk!)
Now, as to checking that "the records point to active hosts", well, I
won't even try for that. What do you mean by "active"?
But, as someone else said, look at "named-checkzone".
Bill
Why don't you load the zonefile you changed into a test dns server and
then compare the queries against prod and your test system? Might be
easier than parsing the file in my opinion.
Regards,
Adrian
Brian
Oh, a challenge. Thanks
Bill
_______________________________________________
bind-users mailing list
bind-...@lists.isc.org
https://lists.isc.org/mailman/listinfo/bind-users
Visit our website at http://www.ubs.com
This message contains confidential information and is intended only
for the individual named. If you are not the named addressee you
should not disseminate, distribute or copy this e-mail. Please
notify the sender immediately by e-mail if you have received this
e-mail by mistake and delete this e-mail from your system.
E-mails are not encrypted and cannot be guaranteed to be secure or
error-free as information could be intercepted, corrupted, lost,
destroyed, arrive late or incomplete, or contain viruses. The sender
therefore does not accept liability for any errors or omissions in the
contents of this message which arise as a result of e-mail transmission.
If verification is required please request a hard-copy version. This
message is provided for informational purposes and should not be
construed as a solicitation or offer to buy or sell any securities
or related financial instruments.
UBS reserves the right to retain all messages. Messages are protected
and accessed only in legally justified cases.
If you're just looking at changes, try something like:
named-checkzone -D -o zone1-canonical.txt example.com zone1.txt
named-checkzone -D -o zone2-canonical.txt example.com zone2.txt
diff -u zone{1,2}-canonical.txt
>
> The named-checkzone program, to my understanding, merely checks for syntax and doesn't do anything with actual verification of the records.
>
>From 'man named-checkzone':
"[named-checkzone] performs the same checks as named does when loading
a zone.... [named-compilezone] applies stricter check levels by
default, since the dump output will be used as an actual zone file
loaded by named."
See options in the man page for checks that are done by default (e.g.,
-i, -k, -m, etc.)
Regards,
Casey
Using some of the suggestions, I kludged together another script. I'm
still fine tuning it. It works great for A and CNAME records, but I'm
tweaking the MX and NS record types.
Comments and critiques are appreciated.
Brian
=====
BEGIN
=====
#!/bin/bash
## named-checkzone_files.sh: verify records between two zone files.
########################################################################
#######
## CHANGE LOG
## Author Date Change
## B. Atkins 20100723 Started program...
########################################################################
#######
## VARIABLES
PATH=$PATH:/usr/sbin/:/usr/local/bin/
########################################################################
#######
## FUNCTIONS
usage() {
cat << EOF
$0 : Verify records between two zone files.
USAGE: $0 -f {FILE} -F {FILE} -z {ZONE} [-A|-a|-c|-m|-n] [-h (Prints
help]
OPTIONS:
-a Check only A records
-A Check ALL record types
-c Check only CNAME records
-f {FILE} Primary zone file {FILE}
-F {FILE} Secondary zone file {FILE}
-m Check only MX records
-n Check only NS records
-z {ZONE} Specify zone to verify
-h Prints this help file
EOF
exit $EXIT
}
make_dump() {
FILE=$1
ZONE=$2
EXTN=`echo ${FILE} | awk -F\/ '{print $NF}'`
[[ -e /tmp/${EXTN}.dumpdb ]] && rm -f /tmp/${EXTN}.dumpdb
echo -n "Creating DB file for ${FILE} ... " &&
named-checkzone -o /tmp/${EXTN}.dumpdb -D ${ZONE} ${FILE} >
/dev/null &&
echo OK || ( echo FAIL && echo -e "Failed to create DB for
${FILE}\nExiting ... " && exit 5 )
}
parse_file() {
FILE1=$1
FILE2=$2
ZONE=$3
TYPE=$4
EXTN1=`echo ${FILE1} | awk -F\/ '{print $NF}'`
EXTN2=`echo ${FILE2} | awk -F\/ '{print $NF}'`
grep "${TYPE}" /tmp/${EXTN1}.dumpdb |
awk '{print $1" "$NF}' |
while read LINE1
do LINE2=(`grep "${TYPE}" /tmp/${EXTN2}.dumpdb | awk
'{print $1" "$NF}' | grep -i "${LINE1[*]}"`)
if [[ -z ${LINE2} ]]
then LINE2=(`grep "${TYPE}" /tmp/${EXTN2}.dumpdb |
awk '{print $1" "$NF}' | grep -i "${LINE1[0]}"`)
if [[ -z ${LINE2} ]]
then echo "${LINE1[*]} ${TYPE}" >>
/tmp/${ZONE}.missing
else : ${LINE1[*]}
LAST1=$_
: ${LINE2[*]}
LAST2=$_
if [[ -z ${IGN} ]]
then if [[ ${LAST1} != ${LAST2} ]]
then echo "${LINE1[*]}
${TYPE}" >> /tmp/${ZONE}.missing
echo -e "\t${LINE2[*]}"
>> /tmp/${ZONE}.missing
else continue
fi
else continue
fi
fi
else continue
fi
done
}
########################################################################
#######
## MAIN PROGRAM
while getopts ":aAcf:F:hmnz:" opt
do case $opt in
a) TYPE="IN A" ;;
A) TYPE="ALL" ;;
c) TYPE="CNAME" ;;
f) FILE1=$OPTARG ;;
F) FILE2=$OPTARG ;;
m) TYPE="MX" ;;
n) TYPE="NS" ;;
z) ZONE=$OPTARG ;;
\?) usage
exit 99 ;;
:) echo "$0 : Option -$OPTARG requires and
argument."
EXIT=99
usage ;;
esac
done
[[ -z ${TYPE} ]] && TYPE="ALL"
[[ -z $FILE1 ]] && EXIT=1 && usage
[[ -z $FILE2 ]] && EXIT=2 && usage
[[ -z $ZONE ]] && EXIT=3 && usage
for FILE in ${FILE1} ${FILE2}
do make_dump ${FILE} ${ZONE}
done
[[ -s /tmp/${ZONE}.missing ]] && rm -f /tmp/${ZONE}.missing
if [[ ${TYPE} == "ALL" ]]
then for TYPE in "IN A" CNAME MX NS
do parse_file ${FILE1} ${FILE2} ${ZONE} "${TYPE}"
done
else parse_file ${FILE1} ${FILE2} ${ZONE} "${TYPE}"
fi
if [[ -s /tmp/${ZONE}.missing ]]
then echo "There are `wc -l /tmp/${ZONE}.missing | awk '{print $1}'`
bad or missing entries for ${ZONE}."
echo "Please review /tmp/${ZONE}.missing and take appropriate
action."
fi
exit 0
===
END
===