Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- # This script is for secure DDNS updates using GSS/TSIG
- # Version: 0.1
- ## CONFIGURATION ##
- # Kerberos realm
- REALM="EXAMPLE.COM"
- # Kerberos principal
- PRINCIPAL="dns-update@${REALM}"
- # Kerberos keytab
- KEYTAB="/etc/krb5.dhcpd.keytab"
- # Kerberos credentials cache
- KRB5CC="/var/run/isc-dhcpd/dhcpd.krb5cc"
- # Use MIT kerberos args instead of heimdal.
- #KRB5MIT="YES"
- # Domain appended to hostname
- DOMAIN="example.com"
- # Space separated list of DNS servers for sending updates to
- NSRVS="ns1.example.com ns2.example.com"
- # Default DNS resource records TTL
- RRTTL="3600"
- # Do not use TXT RRs (rfc4701)
- NOTXTRRS="YES"
- # Default to IPv4
- PROTO="IPv4"
- # Additional nsupdate flags (-g already applied), e.g. "-d" for debug
- #NSUPDFLAGS="-d"
- # Run in the foreground (for manual run only!!!), it's better to use "-d" as script's first argument
- #DEBUG="YES"
- ######################################################
- _usage() {
- if [ "${NOTXTRRS}" == "YES" ]
- then
- echo "Usage:"
- echo "`basename ${0}` add ip-address -h hostname [-m dhcid|mac-address] [-p IP version | --ipv4 | --ipv6] [-t dns-ttl] [-d]"
- echo "`basename ${0}` delete ip-address [-m dhcid|mac-address] [-p IP version | --ipv4 | --ipv6]"
- else
- echo "Usage:"
- echo "`basename ${0}` add ip-address -h hostname -m dhcid|mac-address [-p IP version | --ipv4 | --ipv6] [-t dns-ttl] [-d]"
- echo "`basename ${0}` delete ip-address -m dhcid|mac-address [-p IP version | --ipv4 | --ipv6]"
- fi
- }
- ## VARIABLES ##
- ACTION=${1}
- IP=${2}
- shift && shift
- while [ ! -z ${1} ]
- do
- case "${1}" in
- "-d")
- DEBUG="YES"
- shift
- ;;
- "-m")
- DHCID=${2}
- shift && shift
- ;;
- "-h")
- NAME=${2%%.*}
- shift && shift
- ;;
- "-t")
- RRTTL="${2}"
- shift && shift
- ;;
- "-p")
- PROTO=${2}
- shift && shift
- ;;
- "--ipv4")
- PROTO="IPv4"
- shift
- ;;
- "--ipv6")
- PROTO="IPv6"
- shift
- ;;
- "--help")
- _usage
- exit 0
- ;;
- *)
- echo "Unknown option: ${1}"
- _usage
- exit 1
- esac
- done
- _kerberos() {
- export KRB5_KTNAME="${KEYTAB}"
- export KRB5CCNAME="${KRB5CC}"
- if [ "${KRB5MIT}" = "YES" ]; then
- KLISTARG="-s"
- else
- KLISTARG="-t"
- fi
- klist ${KLISTARG} || kinit -k -t "${KEYTAB}" -c "${KRB5CC}" "${PRINCIPAL}" || { echo "DDNS: kinit failed"; exit 1; }
- }
- _expandv6() {
- # Adapted from https://github.com/mutax/IPv6-Address-checks by
- # Florian Streibelt <[email protected]>
- local __revipv6=${2}
- local INPUT="${1}"
- local O=""
- while [ "${O}" != "${INPUT}" ]; do
- O="${INPUT}"
- # fill all words with zeroes
- INPUT="$( sed 's|:\([0-9a-f]\{3\}\):|:0\1:|g' <<< "${INPUT}" )"
- INPUT="$( sed 's|:\([0-9a-f]\{3\}\)$|:0\1|g' <<< "${INPUT}")"
- INPUT="$( sed 's|^\([0-9a-f]\{3\}\):|0\1:|g' <<< "${INPUT}" )"
- INPUT="$( sed 's|:\([0-9a-f]\{2\}\):|:00\1:|g' <<< "${INPUT}")"
- INPUT="$( sed 's|:\([0-9a-f]\{2\}\)$|:00\1|g' <<< "${INPUT}")"
- INPUT="$( sed 's|^\([0-9a-f]\{2\}\):|00\1:|g' <<< "${INPUT}")"
- INPUT="$( sed 's|:\([0-9a-f]\):|:000\1:|g' <<< "${INPUT}")"
- INPUT="$( sed 's|:\([0-9a-f]\)$|:000\1|g' <<< "${INPUT}")"
- INPUT="$( sed 's|^\([0-9a-f]\):|000\1:|g' <<< "${INPUT}")"
- done
- # now expand the ::
- grep -qs "::" <<< "${INPUT}"
- if [ "$?" -eq 0 ]; then
- GRPS="$(sed 's|[0-9a-f]||g' <<< "${INPUT}" | wc -m)"
- ((GRPS--)) # carriage return
- ((MISSING=8-GRPS))
- for ((i=0;i<$MISSING;i++)); do
- ZEROES="$ZEROES:0000"
- done
- # be careful where to place the :
- INPUT="$( sed 's|\(.\)::\(.\)|\1'$ZEROES':\2|g' <<< "${INPUT}")"
- INPUT="$( sed 's|\(.\)::$|\1'$ZEROES':0000|g' <<< "${INPUT}")"
- INPUT="$( sed 's|^::\(.\)|'$ZEROES':0000:\1|g;s|^:||g' <<< "${INPUT}")"
- fi
- # an expanded address has 39 chars + CR
- if [ $(echo ${INPUT} | wc -m) != 40 ]; then
- echo "Invalid IPv6 Address"
- exit 1
- fi
- LEN=${#INPUT}
- for ((i=LEN-1;i>=0;i--))
- do
- [ ${INPUT:i:1} != ":" ] && TMPSTR=${TMPSTR}"."${INPUT:i:1}
- done
- INPUT=${TMPSTR:1}".ip6.arpa"
- # echo the fully expanded version of the address
- eval ${__revipv6}="'${INPUT}'"
- }
- _main() {
- umask 77
- if [ -z "${IP}" ]
- then
- _usage
- exit 1
- fi
- if [ "${NOTXTRRS}" != "YES" ] && [ -z "${DHCID}" ]
- then
- _usage
- exit 1
- fi
- ## NSUPDATE ##
- case "${ACTION}" in
- add)
- if [ -z "${NAME}" ]
- then
- _usage
- exit 1
- fi
- RRPTR="${NAME}.${DOMAIN}"
- if [ "${NOTXTRRS}" != "YES" ]; then
- NOTXTRRS=""
- RRAOLD=`host ${RRPTR} | awk '/has address/ {print $4}'`
- if [ -n "${RRAOLD}" ]; then
- RRTXTOLD=`host -t txt "${RRPTR}" | sed -n '/descriptive text/s/^.*[[:space:]]descriptive text[[:space:]]*"\(.*\)"$/\1/p'`
- [ -z "${RRTXTOLD}" ] && echo "DDNS: adding records for $ip (${RRPTR}) FAILED: has A record but no DHCID, not mine" && exit 1
- RRTXT=`echo "${DHCID}${RRPTR}" | sha256sum`
- RRTXT="000101${RRTXT%% *}"
- [ "${RRTXT}" != "${RRTXTOLD}" ] && echo "DDNS: adding records for $ip (${RRPTR}) FAILED: has A record but DHCID is wrong" && exit 1
- else
- RRTXT=`echo "${DHCID}${RRPTR}" | sha256sum`
- RRTXT="000101${RRTXT%% *}"
- fi
- else
- NOTXTRRS=";"
- fi
- echo "${PROTO}!"
- case "${PROTO}" in
- "IPv4")
- RRPTRNAME=`echo ${IP} | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}'`
- RECNAME="A"
- ;;
- "IPv6")
- _expandv6 ${IP} RRPTRNAME
- RECNAME="AAAA"
- ;;
- *)
- echo "Unknown IP version: ${PROTO}"
- exit 1
- esac
- _kerberos
- for NSRV in ${NSRVS}; do
- nsupdate -g ${NSUPDFLAGS} << UPDATE
- server ${NSRV}
- realm ${REALM}
- update delete ${RRPTR}. ${RRTTL} ${RECNAME}
- ${NOTXTRRS}update delete ${RRPTR}. ${RRTTL} TXT
- ${NOTXTRRS}update add ${RRPTR}. ${RRTTL} TXT ${RRTXT}
- update add ${RRPTR}. ${RRTTL} ${RECNAME} ${IP}
- send
- update delete ${RRPTRNAME}. ${RRTTL} PTR
- update add ${RRPTRNAME}. ${RRTTL} PTR ${NAME}.${DOMAIN}.
- send
- UPDATE
- RESULT=${?}
- [ "${RESULT}" -eq "0" ] && echo "DDNS: adding records for ${IP} (${RRPTR}) succeeded" && exit 0
- done
- [ "${RESULT}" != "0" ] && echo "DDNS: adding records for ${IP} (${RRPTR}) FAILED: nsupdate status ${RESULT}" && exit "${RESULT}"
- ;;
- delete)
- RRPTR=`host ${IP} | awk '/domain name pointer/ { sub(/\.$/, "", $5); print $5}'`
- if [ "${NOTXTRRS}" != "YES" ]; then
- NOTXTRRS=""
- if [ -n "${RRPTR}" ]; then
- RRTXTOLD=`host -t txt "${RRPTR}" | sed -n '/descriptive text/s/^.*[[:space:]]descriptive text[[:space:]]*"\(.*\)"$/\1/p'`
- [ -z "${RRTXTOLD}" ] && echo "DDNS: removing records for $ip (${RRPTR}) FAILED: has A record but no DHCID, not mine" && exit 1
- RRTXT=`echo "${DHCID}${RRPTR}" | sha256sum`
- RRTXT="000101${RRTXT%% *}"
- [ "${RRTXT}" != "${RRTXTOLD}" ] && echo "DDNS: removing records for ${IP} (${RRPTR}) FAILED: has A record but DHCID is wrong" && exit 1
- else
- echo "DDNS: removing records for ${IP} FAILED: has no PTR, can not determine A record" && exit 1
- fi
- else
- NOTXTRRS=";"
- fi
- case "${PROTO}" in
- "IPv4")
- RRPTRNAME=`echo ${IP} | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}'`
- RECNAME="A"
- ;;
- "IPv6")
- _expandv6 ${IP} RRPTRNAME
- RECNAME="AAAA"
- ;;
- *)
- echo "Unknown IP version: ${PROTO}"
- exit 1
- esac
- _kerberos
- for NSRV in ${NSRVS}; do
- nsupdate -g ${NSUPDFLAGS} << UPDATE
- server ${NSRV}
- realm ${REALM}
- update delete ${RRPTR}. ${RRTTL} ${RECNAME}
- ${NOTXTRRS}update delete ${RRPTR}. ${RRTTL} TXT
- send
- update delete ${RRPTRNAME}. ${RRTTL} PTR
- send
- UPDATE
- RESULT=${?}
- [ "${RESULT}" -eq "0" ] && echo "DDNS: removing records for ${IP} (${RRPTR}) succeeded" && exit 0
- done
- [ "${RESULT}" != "0" ] && echo "DDNS: removing records for ${IP} (${RRPTR}) FAILED: nsupdate status ${RESULT}" && exit "${RESULT}"
- ;;
- *)
- _usage && exit 1
- ;;
- esac
- }
- if [ "$DEBUG" = "YES" ]; then
- _main
- else
- :
- _main | logger -s -t dhcpd &
- fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement