Advertisement
Guest User

dns-krbnsupdate.sh

a guest
Jan 8th, 2014
3,944
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 8.36 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. # This script is for secure DDNS updates using GSS/TSIG
  4. # Version: 0.1
  5.  
  6. ## CONFIGURATION ##
  7. # Kerberos realm
  8. REALM="EXAMPLE.COM"
  9. # Kerberos principal
  10. PRINCIPAL="dns-update@${REALM}"
  11. # Kerberos keytab
  12. KEYTAB="/etc/krb5.dhcpd.keytab"
  13. # Kerberos credentials cache
  14. KRB5CC="/var/run/isc-dhcpd/dhcpd.krb5cc"
  15. # Use MIT kerberos args instead of heimdal.
  16. #KRB5MIT="YES"
  17.  
  18. # Domain appended to hostname
  19. DOMAIN="example.com"
  20. # Space separated list of DNS servers for sending updates to
  21. NSRVS="ns1.example.com ns2.example.com"
  22. # Default DNS resource records TTL
  23. RRTTL="3600"
  24. # Do not use TXT RRs (rfc4701)
  25. NOTXTRRS="YES"
  26. # Default to IPv4
  27. PROTO="IPv4"
  28.  
  29. # Additional nsupdate flags (-g already applied), e.g. "-d" for debug
  30. #NSUPDFLAGS="-d"
  31. # Run in the foreground (for manual run only!!!), it's better to use "-d" as script's first argument
  32. #DEBUG="YES"
  33.  
  34. ######################################################
  35.  
  36. _usage() {
  37.   if [ "${NOTXTRRS}" == "YES" ]
  38.   then
  39.     echo "Usage:"
  40.     echo "`basename ${0}` add ip-address -h hostname [-m dhcid|mac-address] [-p IP version | --ipv4 | --ipv6] [-t dns-ttl] [-d]"
  41.     echo "`basename ${0}` delete ip-address [-m dhcid|mac-address] [-p IP version | --ipv4 | --ipv6]"
  42.   else
  43.     echo "Usage:"
  44.     echo "`basename ${0}` add ip-address -h hostname -m dhcid|mac-address [-p IP version | --ipv4 | --ipv6] [-t dns-ttl] [-d]"
  45.     echo "`basename ${0}` delete ip-address -m dhcid|mac-address [-p IP version | --ipv4 | --ipv6]"
  46.   fi
  47. }
  48.  
  49. ## VARIABLES ##
  50. ACTION=${1}
  51. IP=${2}
  52. shift && shift
  53. while [ ! -z ${1} ]
  54. do
  55.   case "${1}" in
  56.     "-d")
  57.       DEBUG="YES"
  58.       shift
  59.     ;;
  60.     "-m")
  61.       DHCID=${2}
  62.       shift && shift
  63.     ;;
  64.     "-h")
  65.       NAME=${2%%.*}
  66.       shift && shift
  67.     ;;
  68.     "-t")
  69.       RRTTL="${2}"
  70.       shift && shift
  71.     ;;
  72.     "-p")
  73.       PROTO=${2}
  74.       shift && shift
  75.     ;;
  76.     "--ipv4")
  77.       PROTO="IPv4"
  78.       shift
  79.     ;;
  80.     "--ipv6")
  81.       PROTO="IPv6"
  82.       shift
  83.     ;;
  84.     "--help")
  85.       _usage
  86.       exit 0
  87.     ;;
  88.     *)
  89.       echo "Unknown option: ${1}"
  90.       _usage
  91.       exit 1
  92.   esac
  93. done
  94.  
  95. _kerberos() {
  96.   export KRB5_KTNAME="${KEYTAB}"
  97.   export KRB5CCNAME="${KRB5CC}"
  98.  
  99.   if [ "${KRB5MIT}" = "YES" ]; then
  100.     KLISTARG="-s"
  101.   else
  102.     KLISTARG="-t"
  103.   fi
  104.  
  105.   klist ${KLISTARG} || kinit -k -t "${KEYTAB}" -c "${KRB5CC}" "${PRINCIPAL}" || { echo "DDNS: kinit failed"; exit 1; }
  106. }
  107.  
  108. _expandv6() {
  109. # Adapted from https://github.com/mutax/IPv6-Address-checks by
  110. # Florian Streibelt <florian@f-streibelt.de>
  111.   local __revipv6=${2}
  112.   local INPUT="${1}"
  113.   local O=""
  114.  
  115.   while [ "${O}" != "${INPUT}" ]; do
  116.     O="${INPUT}"
  117.  
  118.     # fill all words with zeroes
  119.     INPUT="$( sed  's|:\([0-9a-f]\{3\}\):|:0\1:|g' <<< "${INPUT}" )"
  120.     INPUT="$( sed  's|:\([0-9a-f]\{3\}\)$|:0\1|g'  <<< "${INPUT}")"
  121.     INPUT="$( sed  's|^\([0-9a-f]\{3\}\):|0\1:|g'  <<< "${INPUT}" )"
  122.  
  123.     INPUT="$( sed  's|:\([0-9a-f]\{2\}\):|:00\1:|g' <<< "${INPUT}")"
  124.     INPUT="$( sed  's|:\([0-9a-f]\{2\}\)$|:00\1|g'  <<< "${INPUT}")"
  125.     INPUT="$( sed  's|^\([0-9a-f]\{2\}\):|00\1:|g'  <<< "${INPUT}")"
  126.  
  127.     INPUT="$( sed  's|:\([0-9a-f]\):|:000\1:|g'  <<< "${INPUT}")"
  128.     INPUT="$( sed  's|:\([0-9a-f]\)$|:000\1|g'   <<< "${INPUT}")"
  129.     INPUT="$( sed  's|^\([0-9a-f]\):|000\1:|g'   <<< "${INPUT}")"
  130.   done
  131.  
  132.   # now expand the ::
  133.   grep -qs "::" <<< "${INPUT}"
  134.   if [ "$?" -eq 0 ]; then
  135.     GRPS="$(sed  's|[0-9a-f]||g' <<< "${INPUT}" | wc -m)"
  136.     ((GRPS--)) # carriage return
  137.     ((MISSING=8-GRPS))
  138.     for ((i=0;i<$MISSING;i++)); do
  139.       ZEROES="$ZEROES:0000"
  140.     done
  141.  
  142.     # be careful where to place the :
  143.     INPUT="$( sed  's|\(.\)::\(.\)|\1'$ZEROES':\2|g'   <<< "${INPUT}")"
  144.     INPUT="$( sed  's|\(.\)::$|\1'$ZEROES':0000|g'   <<< "${INPUT}")"
  145.     INPUT="$( sed  's|^::\(.\)|'$ZEROES':0000:\1|g;s|^:||g'   <<< "${INPUT}")"
  146.   fi
  147.  
  148.   # an expanded address has 39 chars + CR
  149.   if [ $(echo ${INPUT} | wc -m) != 40 ]; then
  150.     echo "Invalid IPv6 Address"
  151.     exit 1
  152.   fi
  153.  
  154.   LEN=${#INPUT}
  155.   for ((i=LEN-1;i>=0;i--))
  156.   do
  157.     [ ${INPUT:i:1} != ":" ] && TMPSTR=${TMPSTR}"."${INPUT:i:1}
  158.   done
  159.   INPUT=${TMPSTR:1}".ip6.arpa"
  160.  
  161.   # echo the fully expanded version of the address
  162.   eval ${__revipv6}="'${INPUT}'"
  163. }
  164.  
  165. _main() {
  166.   umask 77
  167.  
  168.   if [ -z "${IP}" ]
  169.   then
  170.     _usage
  171.     exit 1
  172.   fi
  173.  
  174.   if [ "${NOTXTRRS}" != "YES" ] && [ -z "${DHCID}" ]
  175.   then
  176.     _usage
  177.     exit 1
  178.   fi
  179.  
  180.   ## NSUPDATE ##
  181.   case "${ACTION}" in
  182.     add)
  183.       if [ -z "${NAME}" ]
  184.       then
  185.         _usage
  186.         exit 1
  187.       fi
  188.  
  189.       RRPTR="${NAME}.${DOMAIN}"
  190.       if [ "${NOTXTRRS}" != "YES" ]; then
  191.         NOTXTRRS=""
  192.         RRAOLD=`host ${RRPTR} | awk '/has address/ {print $4}'`
  193.         if [ -n "${RRAOLD}" ]; then
  194.           RRTXTOLD=`host -t txt "${RRPTR}" | sed -n '/descriptive text/s/^.*[[:space:]]descriptive text[[:space:]]*"\(.*\)"$/\1/p'`
  195.           [ -z "${RRTXTOLD}" ] && echo "DDNS: adding records for $ip (${RRPTR}) FAILED: has A record but no DHCID, not mine" && exit 1
  196.  
  197.           RRTXT=`echo "${DHCID}${RRPTR}" | sha256sum`
  198.           RRTXT="000101${RRTXT%% *}"
  199.           [ "${RRTXT}" != "${RRTXTOLD}" ] && echo "DDNS: adding records for $ip (${RRPTR}) FAILED: has A record but DHCID is wrong" && exit 1
  200.         else
  201.           RRTXT=`echo "${DHCID}${RRPTR}" | sha256sum`
  202.           RRTXT="000101${RRTXT%% *}"
  203.         fi
  204.       else
  205.         NOTXTRRS=";"
  206.       fi
  207.  
  208.       echo "${PROTO}!"
  209.  
  210.       case "${PROTO}" in
  211.         "IPv4")
  212.            RRPTRNAME=`echo ${IP} | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}'`
  213.            RECNAME="A"
  214.         ;;
  215.         "IPv6")
  216.           _expandv6 ${IP} RRPTRNAME
  217.           RECNAME="AAAA"
  218.         ;;
  219.         *)
  220.           echo "Unknown IP version: ${PROTO}"
  221.           exit 1
  222.       esac
  223.  
  224.       _kerberos
  225.  
  226.       for NSRV in ${NSRVS}; do
  227.         nsupdate -g ${NSUPDFLAGS} << UPDATE
  228. server ${NSRV}
  229. realm ${REALM}
  230. update delete ${RRPTR}. ${RRTTL} ${RECNAME}
  231. ${NOTXTRRS}update delete ${RRPTR}. ${RRTTL} TXT
  232. ${NOTXTRRS}update add ${RRPTR}. ${RRTTL} TXT ${RRTXT}
  233. update add ${RRPTR}. ${RRTTL} ${RECNAME} ${IP}
  234. send
  235. update delete ${RRPTRNAME}. ${RRTTL} PTR
  236. update add ${RRPTRNAME}. ${RRTTL} PTR ${NAME}.${DOMAIN}.
  237. send
  238. UPDATE
  239.  
  240.         RESULT=${?}
  241.         [ "${RESULT}" -eq "0" ] && echo "DDNS: adding records for ${IP} (${RRPTR}) succeeded" && exit 0
  242.       done
  243.  
  244.       [ "${RESULT}" != "0" ] && echo "DDNS: adding records for ${IP} (${RRPTR}) FAILED: nsupdate status ${RESULT}" && exit "${RESULT}"
  245.     ;;
  246.     delete)
  247.       RRPTR=`host ${IP} | awk '/domain name pointer/ { sub(/\.$/, "", $5); print $5}'`
  248.       if [ "${NOTXTRRS}" != "YES" ]; then
  249.         NOTXTRRS=""
  250.         if [ -n "${RRPTR}" ]; then
  251.           RRTXTOLD=`host -t txt "${RRPTR}" | sed -n '/descriptive text/s/^.*[[:space:]]descriptive text[[:space:]]*"\(.*\)"$/\1/p'`
  252.           [ -z "${RRTXTOLD}" ] && echo "DDNS: removing records for $ip (${RRPTR}) FAILED: has A record but no DHCID, not mine" && exit 1
  253.  
  254.           RRTXT=`echo "${DHCID}${RRPTR}" | sha256sum`
  255.           RRTXT="000101${RRTXT%% *}"
  256.           [ "${RRTXT}" != "${RRTXTOLD}" ] && echo "DDNS: removing records for ${IP} (${RRPTR}) FAILED: has A record but DHCID is wrong" && exit 1
  257.         else
  258.           echo "DDNS: removing records for ${IP} FAILED: has no PTR, can not determine A record" && exit 1
  259.         fi
  260.       else
  261.         NOTXTRRS=";"
  262.       fi
  263.  
  264.       case "${PROTO}" in
  265.         "IPv4")
  266.            RRPTRNAME=`echo ${IP} | awk -F '.' '{print $4"."$3"."$2"."$1".in-addr.arpa"}'`
  267.            RECNAME="A"
  268.         ;;
  269.         "IPv6")
  270.           _expandv6 ${IP} RRPTRNAME
  271.           RECNAME="AAAA"
  272.         ;;
  273.         *)
  274.           echo "Unknown IP version: ${PROTO}"
  275.           exit 1
  276.       esac
  277.  
  278.       _kerberos
  279.  
  280.       for NSRV in ${NSRVS}; do
  281.         nsupdate -g ${NSUPDFLAGS} << UPDATE
  282. server ${NSRV}
  283. realm ${REALM}
  284. update delete ${RRPTR}. ${RRTTL} ${RECNAME}
  285. ${NOTXTRRS}update delete ${RRPTR}. ${RRTTL} TXT
  286. send
  287. update delete ${RRPTRNAME}. ${RRTTL} PTR
  288. send
  289. UPDATE
  290.  
  291.         RESULT=${?}
  292.         [ "${RESULT}" -eq "0" ] && echo "DDNS: removing records for ${IP} (${RRPTR}) succeeded" && exit 0
  293.       done
  294.  
  295.       [ "${RESULT}" != "0" ] && echo "DDNS: removing records for ${IP} (${RRPTR}) FAILED: nsupdate status ${RESULT}" && exit "${RESULT}"
  296.     ;;
  297.     *)
  298.       _usage && exit 1
  299.     ;;
  300. esac
  301. }
  302.  
  303. if [ "$DEBUG" = "YES" ]; then
  304.   _main
  305. else
  306.   :
  307.   _main | logger -s -t dhcpd &
  308. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement