Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add support for Knot DNS knsupdate #161

Closed
snassar opened this issue Apr 30, 2016 · 3 comments
Closed

Add support for Knot DNS knsupdate #161

snassar opened this issue Apr 30, 2016 · 3 comments

Comments

@snassar
Copy link

snassar commented Apr 30, 2016

knsupdate doesn't accept values from the command line and need to read from files. I modified dns.hook in the following matter. This seems to work. There are probably more secure ways of implementing this though. If there is interest, I am happy to invest more time in implementing this properly with feedback and some mentorship

#!/bin/bash
# This is an example DNS hook script which uses the knsupdate utility to update
# nameservers. The script waits until updates have propagated to all
# nameservers listed for a zone. The script fails if this takes more than 60
# seconds by default; this timeout can be adjusted.
#
# The script is ready to use, but to use it you must create
# /etc/default/acme-dns or /etc/conf.d/acme-dns and set the following options:
#
#   # Needed if using TKIP for updates. If authenticating updates by source IP,
#   # not necessary.
#   TKIP_KEY_NAME="hmac-sha256:tk1"
#   TKIP_KEY="a base64-encoded TKIP key"
#
#   # DNS synchronization timeout in seconds. Default is 60.
#   DNS_SYNC_TIMEOUT=60
#
#   # Optional: inject extra arguments and commands to nsupdate.
#   NSUPDATE_ARGS="-v"
#   nsupdate_cmds() {
#     # Usually not necessary:
#     echo zone example.com.
#   }
#
# Having done this, rename it to /usr/lib[exec]/acme/hooks/dns.
#
# How to test this script:
#   ./dns.hook challenge-dns-start example.com "" "foobar"
#   ./dns.hook challenge-dns-stop  example.com "" "foobar"
#
set -e

KNSUPDATECMDS="knsupdate_cmds.txt"

get_apex() {
  local name="$1"
  if [ -z "$name" ]; then
    echo "$0: couldn't get apex for $name" >&2
    return 1
  fi
  if [ "`dig +noall +answer SOA "${name}." |grep SOA|wc -l`" == "1" ]; then
    APEX="$name"
    return
  fi
  local sname="$(echo $name | sed 's/^[^.]\+\.//')"
  get_apex "$sname"
}

waitns() {
  local ns="$1"
  for ctr in $(seq 1 "$DNS_SYNC_TIMEOUT"); do
    [ "$(dig +short "@${ns}" TXT "_acme-challenge.${CH_HOSTNAME}." | grep "$CH_TXT_VALUE" | wc -l)" == "1" ] && return 0
    sleep 1
  done

  # Best effort cleanup.
  echo $0: timed out waiting ${DNS_SYNC_TIMEOUT}s for nameserver $ns >&2
  updns del || echo $0: failed to clean up records after timing out >&2

  return 1
}

updns() {
  local op="$1"
  touch $KNSUPDATECMDS
  (
    declare -f knsupdate_cmds >/dev/null && knsupdate_cmds
    [ -n "$TKIP_KEY" ] && echo key "$TKIP_KEY_NAME" "$TKIP_KEY" >> $KNSUPDATECMDS
    echo "zone ${CH_HOSTNAME}." >> $KNSUPDATECMDS
    echo $op "_acme-challenge.${CH_HOSTNAME}." 60 IN TXT "\"${CH_TXT_VALUE}\"" >> $KNSUPDATECMDS
    echo "send" >> $KNSUPDATECMDS
    echo "quit" >> $KNSUPDATECMDS
  ) | knsupdate $KNSUPDATECMDS
  rm $KNSUPDATECMDS
}

[ -e "/etc/default/acme-dns" ] && . /etc/default/acme-dns
[ -e "/etc/conf.d/acme-dns" ] && . /etc/conf.d/acme-dns
# e.g.
#   TKIP_KEY_NAME="hmac-sha256:tk1"
#   TKIP_KEY="base64-key-value"

EVENT_NAME="$1"
CH_HOSTNAME="$2"
CH_TARGET_FILENAME="$3"
CH_TXT_VALUE="$4"
[ -z "$DNS_SYNC_TIMEOUT" ] && DNS_SYNC_TIMEOUT=60

case "$EVENT_NAME" in
  challenge-dns-start)
    get_apex "$CH_HOSTNAME"
    updns add

    # Wait for all nameservers to update.
    for ns in $(dig +short NS "${APEX}."); do
      waitns "$ns"
    done
    ;;

  challenge-dns-stop)
    get_apex "$CH_HOSTNAME"
    updns del
    ;;

  *)
    exit 42
    ;;
esac
@hlandau
Copy link
Owner

hlandau commented Sep 15, 2016

Linked to this issue on the wiki so people can find it. Closing this.

@hlandau hlandau closed this as completed Sep 15, 2016
@cpu
Copy link
Contributor

cpu commented Oct 16, 2016

Thanks for sharing @snassar ! I found this quite useful. However, there's a small bug in the hook code:

L68: [ -n "$TKIP_KEY" ] && echo key "$TKIP_KEY_NAME" "$TKIP_KEY" should be:

L68: [ -n "$TKIP_KEY" ] && echo key "$TKIP_KEY_NAME" "$TKIP_KEY" >> $KNSUPDATECMDS

Otherwise if using TKIP authentication the key command is echoed to stdout and not the $KNSUPDATECMDS file that is used as input for knsupdate.

@hlandau Is it possible for yourself or @snassar to fix this in the issue description since the wiki links here?

Thanks again!!

@hlandau
Copy link
Owner

hlandau commented Oct 17, 2016

@cpu Done.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants