Recently I got an unusual request to create 2 CNAMES for a client for which we're doing a lot of stuff and also DNS-hosting.
They will be moving their site to some clever load-balancing webserver.
The CNAME needed to be created on the www.client.com and on the client.com
The latter is not possible in Plesk nor in Bind.
Here's some more info (which I didn't read all):
Introducing CNAME Flattening: RFC-Compliant CNAMEs at a Domain's Root
Why it's a bad idea to put a CNAME record on your root domain
CNAME Flattening: RFC-Compliant CNAMEs at a Domain's Root | Hacker News
I gave it all kind of thoughts and after trying some other workarounds I decided to simulate their cname flattening trick using a normal Plesk.
I have it as an hourly cronjob. The TTL on their CNAME is 60 seconds and they have a pool of 12 IP's of which 4 IP's are taken out on a regular basis. The IP's that are taken out keep responding to the http-requests (I tested this by putting 1 of those IP's in my /etc/hosts). It also keeps some tracking, so you know what that other DNS-provider is doing. Use it if you think it fits your scenario.
The script can run in 2 modes
With "USE_PLESK_CLI=true" it will use Plesk's dns command to add/remove records.
With "USE_PLESK_CLI=" it will manipulate the zonefiles directly
If you want a high update frequency (beneath an hour) it might be better to let it manipulate the zonefiles directly.
[Edit] I wouldn't use the mode that directly edits the zonefile as of yet. I have trouble getting it to sync with the slave server.
I'm updating the serial, but it doesn't come over.
Maybe I will replace the published code with the USE_PLESK_CLI mode only.
I'm open for suggestions or questions.
BTW: I still advised the webmaster to redirect immediately from https://clientdomain.com to https://www.clientdomain.com. This way, the amount of users actually going to the bare domain should remain minimal.
cat /usr/local/sbin/flattencnames.conf
# cat /usr/local/sbin/flattencnames
As a test it's now running as a 5-minute cronjob (I would suggest using 1 hour):
The first datestamp is the initial registration, the 2nd one is the last registration.
Then at the end there's a number representing the times that IP had to be re-added.
# cat /var/log/flattencnames-client.com.log
They will be moving their site to some clever load-balancing webserver.
The CNAME needed to be created on the www.client.com and on the client.com
The latter is not possible in Plesk nor in Bind.
Here's some more info (which I didn't read all):
Introducing CNAME Flattening: RFC-Compliant CNAMEs at a Domain's Root
Why it's a bad idea to put a CNAME record on your root domain
CNAME Flattening: RFC-Compliant CNAMEs at a Domain's Root | Hacker News
I gave it all kind of thoughts and after trying some other workarounds I decided to simulate their cname flattening trick using a normal Plesk.
I have it as an hourly cronjob. The TTL on their CNAME is 60 seconds and they have a pool of 12 IP's of which 4 IP's are taken out on a regular basis. The IP's that are taken out keep responding to the http-requests (I tested this by putting 1 of those IP's in my /etc/hosts). It also keeps some tracking, so you know what that other DNS-provider is doing. Use it if you think it fits your scenario.
The script can run in 2 modes
With "USE_PLESK_CLI=true" it will use Plesk's dns command to add/remove records.
With "USE_PLESK_CLI=" it will manipulate the zonefiles directly
If you want a high update frequency (beneath an hour) it might be better to let it manipulate the zonefiles directly.
[Edit] I wouldn't use the mode that directly edits the zonefile as of yet. I have trouble getting it to sync with the slave server.
I'm updating the serial, but it doesn't come over.
Maybe I will replace the published code with the USE_PLESK_CLI mode only.
I'm open for suggestions or questions.
BTW: I still advised the webmaster to redirect immediately from https://clientdomain.com to https://www.clientdomain.com. This way, the amount of users actually going to the bare domain should remain minimal.
cat /usr/local/sbin/flattencnames.conf
Code:
client.com client.com.herokudns.com.
# cat /usr/local/sbin/flattencnames
Code:
#!/bin/bash
# Booleans
USE_PLESK_CLI=
USE_PLESK_CLI=true
MUTATED=
HEADLESS=
TAB="`echo -en '\t'`"
tty >/dev/null || HEADLESS=true
# Constants
THISSCRIPT="`readlink -f $0`"
CONFIG="${THISSCRIPT}.conf"
SCRIPTNAME=${THISSCRIPT##*/}
TMPDIR=`mktemp -t -d ${SCRIPTNAME}.XXXXXXXXXX`
TRACKERPREFIX="/var/log/${SCRIPTNAME}"
ZONEDIR=/var/named/run-root/var
# check some prerequisites
if [ ! -e "${CONFIG}" ] ; then
echo "I'm expecting a config file with CNAMES to be flattened: ${CONFIG}" >&2
exit 1
fi
if [ ! ${USE_PLESK_CLI} ] ; then
if [ ! -d "${ZONEDIR}" ] ; then
echo "The folder ${ZONEDIR} where I expect the zonefiles doesn't exist!" >&2
exit 1
fi
fi
mutrecords()
{
MUTATED=true
ACTION=$1
echo ${ACTION} | egrep -q "^(add|del)$" || exit 1
[ ${HEADLESS} ] || echo -e "${ACTION} record: ${DOMAIN}\tIN A\t${IP}" >&2
if [ ${USE_PLESK_CLI} ] ; then
/usr/local/psa/bin/dns --${ACTION} ${DOMAIN} -a "" -ip ${IP} 2>&1 >${TMPDIR}/dnsoutput
[ ${HEADLESS} ] || cat ${TMPDIR}/dnsoutput >&2
else
# Modify zonefile directly (outside Plesk)
# This means that the Plesk Panel doesn't represent the actual status of the bare A-records
# On the other hand the database entries can't be modified while you're busy editing
# Maybe use this method if you want to run this script more often than once an hour.
if [ ! -f "${ZONEDIR}/${DOMAIN}" ] ; then
echo "The Zonefile ${ZONEDIR}/${DOMAIN} doesn't exist, I can't do anything" >&2
else
if [ "${ACTION}" = "del" ] ; then
sed -i -e "/^${DOMAIN}\..*IN A.*${IP}$/d" ${ZONEDIR}/${DOMAIN}
else
sed -i -e "1,/^${DOMAIN}\..*IN A/ {/^${DOMAIN}\..*IN A.*/i\
${DOMAIN}.${TAB}${TAB} IN A${TAB} ${IP}
}" ${ZONEDIR}/${DOMAIN}
fi
fi
fi
}
update_tracker()
{
[ -f "${TRACKER_FILE}" ] || touch "${TRACKER_FILE}"
IP_AND_TIME="`echo $IP | awk '{ printf("%-15s",$0)}'`\t${TIME}"
if grep -q "^${GREP_IP}" "${TRACKER_FILE}" ; then
OLDCOUNTER=`grep "^${GREP_IP}" "${TRACKER_FILE}" | awk '{print $6}' | tr -cd '0-9'`
[ -z "${OLDCOUNTER}" ] && OLDCOUNTER=0
COUNTER=$((${OLDCOUNTER} + 1))
REPLACEMENT="`grep "^${GREP_IP}" "${TRACKER_FILE}" | cut -b1-31`\t${TIME}\t${COUNTER}"
sed -i -e "s/^${IP}.*/${REPLACEMENT}/g" "${TRACKER_FILE}"
else
echo -e "${IP_AND_TIME}\tNEW" >>"${TRACKER_FILE}"
fi
}
# Remove commented and empty lines
sed -e '/^\s*#/d;/^\s*$/d' ${CONFIG} >${TMPDIR}/config
while read LINE ; do
DOMAIN="`echo ${LINE} | awk '{print $1}' | tr 'A-Z' 'a-z' | egrep -o '[a-z0-9-]+\.[a-z0-9-]+'`"
CNAME="`echo ${LINE} | awk '{print $2}' | tr 'A-Z' 'a-z' | egrep -o '[a-z0-9.-]+' | sed 's/\.$//'`"
ARECORDS=${TMPDIR}/${DOMAIN}
CNAMEIPS=${TMPDIR}/${DOMAIN}.cnameips
TIME="`date +%d-%b-%y\ %H:%M`"
TRACKER_FILE="${TRACKERPREFIX}-${DOMAIN}.log"
if [ ! -z "${DOMAIN}" ] ; then
host ${DOMAIN} localhost | grep -o 'has address .*' | egrep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort -n >${ARECORDS}
host ${CNAME} | grep -o 'has address .*' | egrep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort -n >${CNAMEIPS}
if [ ! -s ${CNAMEIPS} ] ; then
[ ${HEADLESS} ] || echo "${CNAME} doesn't resolve to ipv4 addresses, I'm skipping this domain (${DOMAIN})" >&2
else
if diff ${ARECORDS} ${CNAMEIPS} >${TMPDIR}/difference ; then
[ ${HEADLESS} ] || echo "${DOMAIN}: nothing changed"
else
grep '^<' ${TMPDIR}/difference | egrep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' >${TMPDIR}/delete
grep '^>' ${TMPDIR}/difference | egrep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' >${TMPDIR}/add
DELETED=`grep -c . ${TMPDIR}/delete`
ADDED=`grep -c . ${TMPDIR}/add`
echo "${DOMAIN}: ${DELETED} record(s) deleted and ${ADDED} record(s) added"
while read IP ; do
GREP_IP="`echo ${IP} | sed 's/\./\\./g'`" # change dots to backslash dots for more precise searching
mutrecords add
update_tracker
done<${TMPDIR}/add
while read IP ; do
GREP_IP="`echo ${IP} | sed 's/\./\\./g'`" # change dots to backslash dots for more precise searching
mutrecords del
done<${TMPDIR}/delete
if [ ! ${USE_PLESK_CLI} ] ; then
OLDSERIAL=`grep '; Serial' ${ZONEDIR}/${DOMAIN} | awk '{print $1}'`
SERIAL=$(( ${OLDSERIAL} + 1))
sed -i "s/${OLDSERIAL}/${SERIAL}/" ${ZONEDIR}/${DOMAIN}
rndc reload ${DOMAIN} 2>&1 >/dev/null
fi
fi
fi
fi
done<${TMPDIR}/config
rm -r ${TMPDIR}
As a test it's now running as a 5-minute cronjob (I would suggest using 1 hour):
Code:
ln -s /usr/local/sbin/flattencnames /etc/cron.5min/
The first datestamp is the initial registration, the 2nd one is the last registration.
Then at the end there's a number representing the times that IP had to be re-added.
# cat /var/log/flattencnames-client.com.log
Code:
46.137.179.247 12-Apr-17 12:59 12-Apr-17 17:00 16
46.51.179.164 12-Apr-17 12:59 12-Apr-17 17:00 15
54.217.215.80 12-Apr-17 12:59 12-Apr-17 16:55 14
54.228.204.220 12-Apr-17 12:59 12-Apr-17 16:55 13
54.228.233.224 12-Apr-17 12:59 12-Apr-17 17:05 13
54.228.244.215 12-Apr-17 12:59 12-Apr-17 17:05 13
176.34.254.113 12-Apr-17 12:59 12-Apr-17 17:00 11
54.246.108.43 12-Apr-17 12:59 12-Apr-17 17:05 11
54.247.71.175 12-Apr-17 13:05 12-Apr-17 17:05 10
54.247.88.150 12-Apr-17 13:05 12-Apr-17 16:20 7
54.247.97.70 12-Apr-17 13:05 12-Apr-17 16:50 7
176.34.180.226 12-Apr-17 13:05 12-Apr-17 17:00 11
Last edited: