#!/bin/bash CONFIGFILE="/etc/default/dnscrypt-wrapper" DAEMON="/usr/sbin/dnscrypt-wrapper" . $CONFIGFILE start_instance() { if [ -z ${PIDFILE[$1]} ]; then echo "No configuration for instance $1 found!" return fi if [ -r ${PIDFILE[$1]} ]; then PID=$(cat ${PIDFILE[$1]}) if [ -z "$PID" ] || ! kill -0 $PID ; then echo "Removing stale PID file..." rm -f ${PIDFILE[$1]} else echo "dnscrypt-wrapper (instance $1) already running!" return fi fi # dnscrypt-wrapper will NOT work without this. /dev/urandom is required in # the chroot. if [ -n "${CHROOTDIR[$1]}" ]; then if [ "$(readlink -f ${CHROOTDIR[$1]})" != "/" ]; then if [ ! -d ${CHROOTDIR[$1]} ]; then mkdir -p ${CHROOTDIR[$1]} chmod 755 ${CHROOTDIR[$1]} fi if [ ! -d ${CHROOTDIR[$1]}/dev ]; then mkdir -p ${CHROOTDIR[$1]}/dev chmod 755 ${CHROOTDIR[$1]}/dev fi if [ ! -c ${CHROOTDIR[$1]}/dev/urandom ]; then mknod -m 666 ${CHROOTDIR[$1]}/dev/urandom c 1 9 fi fi fi mkdir -p $(dirname ${PIDFILE[$1]}) # The child (unprivileged) process needs write access or the PID will not # be written. chmod 0700 $(dirname ${PIDFILE[$1]}) chown ${USER[$1]} $(dirname ${PIDFILE[$1]}) OPTIONS="-d" if [ -n "${LISTENADDRESS[$1]}" ]; then OPTIONS="${OPTIONS} --listen-address=${LISTENADDRESS[$1]}" fi if [ -n "${PIDFILE[$1]}" ]; then OPTIONS="${OPTIONS} --pidfile=${PIDFILE[$1]}" fi if [ -n "${USER[$1]}" ]; then OPTIONS="${OPTIONS} --user=${USER[$1]}" fi if [ -n "${DNSCRYPTDIR[$1]}" ]; then if [ -n "$2" ] && [ "$2" == "rotate" ]; then OPTIONS="${OPTIONS} --crypt-secretkey-file=${DNSCRYPTDIR[$1]}/crypt_secret.key,${DNSCRYPTDIR[$1]}/crypt_secret.key_prev" else OPTIONS="${OPTIONS} --crypt-secretkey-file=${DNSCRYPTDIR[$1]}/crypt_secret.key" fi OPTIONS="${OPTIONS} --provider-publickey-file=${DNSCRYPTDIR[$1]}/public.key" OPTIONS="${OPTIONS} --provider-secretkey-file=${DNSCRYPTDIR[$1]}/secret.key" fi if [ -z "${DNSCRYPTDIR[$1]}" ] && [ -n "${CRYPTSECRETKEYFILE[$1]}" ]; then OPTIONS="${OPTIONS} --crypt-secretkey-file=${CRYPTSECRETKEYFILE[$1]}" fi if [ -z "${DNSCRYPTDIR[$1]}" ] && [ -n "${PROVIDERPUBLICKEYFILE[$1]}" ]; then OPTIONS="${OPTIONS} --provider-publickey-file=${PROVIDERPUBLICKEYFILE[$1]}" fi if [ -z "${DNSCRYPTDIR[$1]}" ] && [ -n "${PROVIDERSECRETKEYFILE[$1]}" ]; then OPTIONS="${OPTIONS} --provider-secretkey-file=${PROVIDERSECRETKEYFILE[$1]}" fi if [ -n "${RESOLVERADDRESS[$1]}" ]; then OPTIONS="${OPTIONS} --resolver-address=${RESOLVERADDRESS[$1]}" fi if [ -n "${PROVIDERNAME[$1]}" ]; then OPTIONS="${OPTIONS} --provider-name=${PROVIDERNAME[$1]}" fi if [ -n "${PROVIDERCERTFILE[$1]}" ]; then if [ -n "$2" ] && [ "$2" == "rotate" ]; then OPTIONS="${OPTIONS} --provider-cert-file=${PROVIDERCERTFILE[$1]},${PROVIDERCERTFILE[$1]}_prev" else OPTIONS="${OPTIONS} --provider-cert-file=${PROVIDERCERTFILE[$1]}" fi fi if [ "${UNAUTHENTICATED[$1]}" == "yes" ]; then OPTIONS="${OPTIONS} --unauthenticated" fi if [ -n "${LOGFILE[$1]}" ]; then OPTIONS="${OPTIONS} --logfile=${LOGFILE[$1]}" fi $DAEMON $OPTIONS } stop_instance() { if [ -z ${PIDFILE[$1]} ]; then echo "No configuration for instance $1 found!" return fi if [ ! -r ${PIDFILE[$1]} ]; then echo "dnscrypt-wrapper (instance $1) is not running!" return fi echo "Stopping dnscrypt-wrapper (instance $1)..." kill $(cat ${PIDFILE[$1]}) rm -f ${PIDFILE[$1]} } status_instance() { if [ -z ${PIDFILE[$1]} ]; then echo "No configuration for instance $1 found!" return fi if [ ! -r ${PIDFILE[$1]} ]; then echo "dnscrypt-wrapper (instance $1) is not running." return fi PID=$(cat ${PIDFILE[$1]}) if [ -z "$PID" ]; then echo "PID file is empty! dnscrypt-wrapper (instance $1) does not appear to be running, but there is a stale PID file." elif kill -0 $PID ; then echo "dnscrypt-wrapper (instance $1) is running." else echo "dnscrypt-wrapper (instance $1) is not running, but there is a stale PID file." fi } generate-keys_instance() { if [ -z ${PIDFILE[$1]} ]; then echo "No configuration for instance $1 found!" return fi if [ -z ${DNSCRYPTDIR[$1]} ]; then echo "DNSCRYPTDIR not set for instance $1! Either set DNSCRYPTDIR or generate keys manually." return fi OPTIONS="" if [ "${NOLOG[$1]}" == "yes" ]; then OPTIONS="${OPTIONS} --nolog" fi if [ "${DNSSEC[$1]}" == "yes" ]; then OPTIONS="${OPTIONS} --dnssec" fi ( echo "Generating keys for instance $1. You should record the fingerprint, since this will be used by clients." cd ${DNSCRYPTDIR[$1]} rm -f public.key secret.key $DAEMON $OPTIONS --gen-provider-keypair \ --provider-name=${PROVIDERNAME[$1]} \ --ext-address=${EXTADDRESS[$1]} chmod 0600 public.key secret.key ) } generate-cryptkeys_instance() { if [ -z ${PIDFILE[$1]} ]; then echo "No configuration for instance $1 found!" return fi if [ -z ${DNSCRYPTDIR[$1]} ]; then echo "DNSCRYPTDIR not set for instance $1! Either set DNSCRYPTDIR or generate keys manually." return fi ( echo "Generating cryptkeys for instance $1." cd ${DNSCRYPTDIR[$1]} rm -f crypt_secret.key $DAEMON --gen-crypt-keypair chmod 0600 crypt_secret.key ) } generate-cert_instance() { if [ -z ${PIDFILE[$1]} ]; then echo "No configuration for instance $1 found!" return fi if [ -z ${PROVIDERCERTFILE[$1]} ]; then echo "PROVIDERCERTFILE for instance $1 not set! Set PROVIDERCERTFILE before generating a certificate." return fi OPTIONS="" if [ -n "${DNSCRYPTDIR[$1]}" ]; then OPTIONS="${OPTIONS} --crypt-secretkey-file=${DNSCRYPTDIR[$1]}/crypt_secret.key" OPTIONS="${OPTIONS} --provider-publickey-file=${DNSCRYPTDIR[$1]}/public.key" OPTIONS="${OPTIONS} --provider-secretkey-file=${DNSCRYPTDIR[$1]}/secret.key" fi if [ -z "${DNSCRYPTDIR[$1]}" ] && [ -n "${CRYPTSECRETKEYFILE[$1]}" ]; then OPTIONS="${OPTIONS} --crypt-secretkey-file=${CRYPTSECRETKEYFILE[$1]}" fi if [ -z "${DNSCRYPTDIR[$1]}" ] && [ -n "${PROVIDERPUBLICKEYFILE[$1]}" ]; then OPTIONS="${OPTIONS} --provider-publickey-file=${PROVIDERPUBLICKEYFILE[$1]}" fi if [ -z "${DNSCRYPTDIR[$1]}" ] && [ -n "${PROVIDERSECRETKEYFILE[$1]}" ]; then OPTIONS="${OPTIONS} --provider-secretkey-file=${PROVIDERSECRETKEYFILE[$1]}" fi if [ -n "${CERTEXPIRATION[$1]}" ]; then OPTIONS="${OPTIONS} --cert-file-expire-days=${CERTEXPIRATION[$1]}" fi ( echo "Generating certificate for instance $1." mkdir /tmp/dnscrypt-wrapper-$$ cd /tmp/dnscrypt-wrapper-$$ $DAEMON $OPTIONS --gen-cert-file chmod 0600 dnscrypt.cert mv -f dnscrypt.cert ${PROVIDERCERTFILE[$1]} cd / rmdir /tmp/dnscrypt-wrapper-$$ ) } rotate-keys_instance() { if [ -z ${PIDFILE[$1]} ]; then echo "No configuration for instance $1 found!" return fi if [ -z ${DNSCRYPTDIR[$1]} ]; then echo "DNSCRYPTDIR not set for instance $1! Either set DNSCRYPTDIR or rotate keys manually." return fi if [ -z ${PROVIDERCERTFILE[$1]} ]; then echo "PROVIDERCERTFILE for instance $1 not set! Set PROVIDERCERTFILE before rotating keys." return fi ( echo "Backing up existing keys for instance $1." cd ${DNSCRYPTDIR[$1]} cp -f crypt_secret.key crypt_secret.key_prev cp -f ${PROVIDERCERTFILE[$1]} ${PROVIDERCERTFILE[$1]}_prev chmod 0600 crypt_secret.key_prev ${PROVIDERCERTFILE[$1]}_prev generate-cryptkeys_instance $1 generate-cert_instance $1 stop_instance $1 sleep 1 start_instance $1 "rotate" ) } start() { for i in `/usr/bin/seq 0 $((${#PIDFILE[@]}-1))` do start_instance $i done } stop() { for i in `/usr/bin/seq 0 $((${#PIDFILE[@]}-1))` do stop_instance $i done } status() { for i in `/usr/bin/seq 0 $((${#PIDFILE[@]}-1))` do status_instance $i done } generate-keys() { for i in `/usr/bin/seq 0 $((${#PIDFILE[@]}-1))` do generate-keys_instance $i done } generate-cryptkeys() { for i in `/usr/bin/seq 0 $((${#PIDFILE[@]}-1))` do generate-cryptkeys_instance $i done } generate-cert() { for i in `/usr/bin/seq 0 $((${#PIDFILE[@]}-1))` do generate-cert_instance $i done } rotate-keys() { for i in `/usr/bin/seq 0 $((${#PIDFILE[@]}-1))` do rotate-keys_instance $i done } case "$1" in 'start') start ;; 'stop') stop ;; 'restart') stop start ;; 'status') status ;; 'generate-keys') generate-keys ;; 'generate-cryptkeys') generate-cryptkeys ;; 'generate-cert') generate-cert ;; 'rotate-keys') rotate-keys ;; *_start) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` start_instance $INSTANCE ;; *_stop) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` stop_instance $INSTANCE ;; *_restart) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` stop_instance $INSTANCE sleep 1 start_instance $INSTANCE ;; *_status) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` status_instance $INSTANCE ;; *_generate-keys) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` generate-keys_instance $INSTANCE ;; *_generate-cryptkeys) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` generate-cryptkeys_instance $INSTANCE ;; *_generate-cert) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` generate-cert_instance $INSTANCE ;; *_rotate-keys) INSTANCE=`echo $1 | /bin/cut -d '_' -f 1` rotate-keys_instance $INSTANCE ;; *) echo "Usage: $0 {start|stop|restart|status|generate-keys|generate-cryptkeys|generate-cert|rotate-keys|#_start|#_stop|#_restart|#_status|#_generate-keys|#_generate-cryptkeys|#_generate-cert|#_rotate-keys}" exit 1 ;; esac