Categories
Internet Rants

Dyn SLA Update – or, How To Lose Friends and Alienate Customers

I today received an email from Dyn (previously DynDNS), stating:

Starting now, if you would like to maintain your free Dyn account, you must log into your account once a month. Failure to do so will result in expiration and loss of your hostname. Note that using an update client will no longer suffice for this monthly login.

(emphasis theirs)

Now, if this were a service which requires interaction then this would be an unfriendly but potentially fair way to weed-out inactive accounts. This isn’t one of those cases, though – I can happily go for months or even years where my only interaction with Dyn(DNS) is via auto-update clients. And this is the heart of the problem – many routers and embedded devices have built-in DynDNS clients, frequently with no option to switch to an alternative service. Possibly this is worth $25/year, possibly it isn’t. Personally, I’m not paying a penny to a company trying to hold its users to ransom like this. For my usage, there are a handful for hostnames in a Dyn(DNS) domain – and therefore these cannot to transferred to a different provider. I keep them going purely so that historic links will still work.

And, to resolve the immediate problem, I wrote this script which can be scheduled to run every 15 days in order to keep my account active – enjoy!

#!/bin/bash

LOGIN="****"
PASSWORD="****"

COOKIES="/tmp/.dynsdns.cookies.txt"
AL="en-gb"
#UA="Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/0.0.0 (KHTML, like Gecko) Version/0.0.0 Safari/0.0.0"

LOGINURL="https://account.dyn.com/entrance/"
POSTURL="$LOGINURL"
CHKURL="https://account.dyn.com/"

(( DEBUG )) && DST="-" || DST="/dev/null"

[[ -w "$( dirname "$COOKIES" )" ]] || { echo >&2 "FATAL: Cannot write to directory '$( dirname "$COOKIES" )'" ; exit 1; }

# Ensure no broken session caching...
if [[ -s "$COOKIES" ]]; then
	[[ -w "$COOKIES" ]] || { echo >&2 "FATAL: Cannot write to file '$COOKIES'" ; exit 1 ; }
	rm -f "$COOKIES" >/dev/null 2>&1
fi

(( DEBUG )) && echo >&2 "DEBUG: Fetching initial headers to pre-load cookies..."
curl -b $COOKIES -c $COOKIES -Ikso "$DST" -A "$UA" --url "$LOGINURL"

(( DEBUG )) && echo >&2 "DEBUG: Fetching UID..."
VALUE="$(
	   curl -b $COOKIES -c $COOKIES -kso - -A "$UA" --url "$LOGINURL" | \
	   grep -m 1 "multiform" | \
	   cut -d"'" -f 6
)"

(( DEBUG )) && echo >&2 "DEBUG: Read UID as '$VALUE' - posting data..."
curl -b $COOKIES -c $COOKIES -d "username=$LOGIN" -d "password=$PASSWORD" -d "iov_id" -d "multiform=$VALUE" -e "$LOGINURL" -kso "$DST" -A "$UA" --url "$POSTURL"

(( DEBUG )) && echo >&2 "DEBUG: Response received - verifying result..."
curl -b $COOKIES -c $COOKIES -e "$POSTURL" -kso - -A "$UA" -H "Accept-Language: $AL" --url "$CHKURL" | \
	   grep -qE "<span>(Welcome|Hi)&nbsp;<b>$LOGIN</b></span>" \
	&& echo "Login successful" \
	|| { echo >&2 "Login failed" ; exit 1 ; }

exit 0

Download this script from http://files.stuart.shelton.me/unix/dyndns-login.sh.

48 replies on “Dyn SLA Update – or, How To Lose Friends and Alienate Customers”

sorry, does not work for me:

DEBUG: Fetching UID...
DEBUG: Read UID as 'EDE102E60F53B36775683E66566F5307B2' - posting data...

302 Found

Found
The document has moved <a HREF="https://account.dyn.com/" rel="nofollow":gt;here</a>.

DEBUG: Response received - verifying result...
mktemp: invalid template, `./dyndns.sh.XXXXXXXX', contains directory separator
mktemp failed: 1

@Ruediger: My bad, I was thinking of the GNU ‘--tmpdir‘ option (which you’ll likely be missing if you’re on Red Hat or not-Linux). Change the first line to:

FILE="$( mktemp -t "$( basename "$0" ).XXXXXXXX" )" || { echo >&2 "mktemp failed: $?" ; exit 1 ; }

First to say: Nice script – thanks for that.

I maintain multiple accounts on dyndns so i have modified the script to be able to handle multiple accounts and added a sleep which hopefully helps to disguise it a bit 🙂 Further i wanted to have an email alert as this accounts are very important for me. For one account I figured out the same problem which was described by Stuart. One account has the welcome message “Welcome”, the other one shows “Hi”. I have modified this as well.

Find my code below and feel free to use and modify it

#!/usr/bin/env bash

LOGIN=(     'account1'   'account2'   'accountn' )
PASSWORD=(  'password1'  'password2'  'passwordn' )
#UA="Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/0.0.0 (KHTML, like Gecko) Version/0.0.0 Safari/0.0.0"

EMAIL='myemail@example.com'

COOKIES="/tmp/.dynsdns.cookies.txt"

LOGINURL="https://account.dyn.com/entrance/"
POSTURL="$LOGINURL"
CHKURL="https://account.dyn.com/"

(( DEBUG )) && DST="-" || DST="/dev/null"

for i in ${!LOGIN[*]};
do (
        # Ensure no broken session caching...
        [[ -s "$COOKIES" ]] && rm "$COOKIES"

        (( DEBUG )) && echo >&2 "DEBUG: Fetching initial headers to pre-load cookies..."
        curl -b $COOKIES -c $COOKIES -Ikso "$DST" -A "$UA" --url "$LOGINURL"
        (( DEBUG )) && echo >&2 "DEBUG: Fetching UID..."
        VALUE="$( curl -b $COOKIES -c $COOKIES -kso - -A "$UA" --url "$LOGINURL" | grep -m 1 "multiform" | cut -d"'" -f 6 )"
        (( DEBUG )) && echo >&2 "DEBUG: Read UID as '$VALUE' - posting data..."
        curl -b $COOKIES -c $COOKIES -d "username=${LOGIN[$i]}" -d "password=${PASSWORD[$i]}" -d "iov_id" -d "multiform=$VALUE" -e "$LOGINURL" -kso "$DST" -A "$UA" --url "$POSTURL"
        (( DEBUG )) && echo >&2 "DEBUG: Response received - verifying result..."
        curl -b $COOKIES -c $COOKIES -e "$POSTURL" -kso - -A "$UA" --url "$CHKURL" | grep -qE "<span>(Welcome|Hi)&nbsp;<b>${LOGIN[$i]}</b></span>" && (echo "Login successful" | mutt -s "DynDNS ${LOGIN[$i]} successful" -- $EMAIL) || (echo "Login failed" | mutt -s "DynDNS ${LOGIN[$i]} failed" -- $EMAIL)
        sleep 5$i.$RANDOM );
done

Hello Stuart,
Thank you for your support. I am using OpenSuse. Does not work for me. The page is fetched, but then the script does not continue. Final output see below:

(function(){
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.type = 'text/javascript'; g.defer = true; g.async = true;
g.src = document.location.protocol + '//dyn3.apptegic.com/scripts/apptegic-tw.min.js';
s.parentNode.insertBefore(g, s);
})();
</script>
</body>
</html>
<!-- page generated successfully -->

Then it stops and I have to cancel script via ctrl-c.

@Ruediger: That’s pretty much the end save for the login check, and the best way to confirm that is probably to add ‘set -o xtrace‘ near the top of the script – from that point onwards, there should be very verbose output detailing the exact commands being invoked. The last of these output is likely where the problem lies…

Done: Following output (replaced plan text of login name):

(function(){
var d = document, g = d.createElement(‘script’), s = d.getElementsByTagName(‘script’)[0];
g.type = ‘text/javascript’; g.defer = true; g.async = true;
g.src = document.location.protocol + ‘//dyn3.apptegic.com/scripts/apptegic-tw.min.js’;
s.parentNode.insertBefore(g, s);
})();


+ grep -q ‘Welcome MyLogin

@Ruediger: Hmm – I think that angle-brackets in your comment have confused WordPress, and it’s swallowed most of your comment 🙁

Could you email the result to me or try pasting it in a comment again surrounded by ‘<pre>’/'</pre>’ tags?

Update: Script updated (and download link added to top of page). By setting an ‘Accept-Language’ header, I’m hoping that the login screen will always show ‘Welcome’, overriding whatever default language the account may be set to. This assumes that Dyn does track different languages, and pays any attention to this header. Please let me know if this has made any difference…

Hello Stuart,
grate work! Now it is working fine for all 3 accounts. I have also made negative tests with wrong login data and it worked as expected. Thank you very much for your effort and sharing it! Thumbs up!

Greetings
Ruediger

Hello,
great work and many thanks to the creators of this script !

To use this feature with a Fritzbox (with freetz+curl), I modified the code a little bit and scheduled it with cron.

#!/bin/sh

#DEBUG=1

LOGIN="***"
PASSWORD="***"
EMAIL="***"

COOKIES="/tmp/.dynsdns.cookies.txt"
AL="en-gb"
UA="Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"
LOGINURL="https://account.dyn.com/entrance/"
POSTURL="$LOGINURL"
CHKURL="https://account.dyn.com/"

[[ $DEBUG ]] && DST="-" || DST="/dev/null"

# random sleep time 1-6000
DELAY=$(($(hexdump -n 2 -e '"%u"' /dev/urandom) % 6000 + 1))
echo >&2 "Wait '$DELAY' sec..."
sleep $DELAY

[[ -w "$( dirname "$COOKIES" )" ]] || { echo >&2 "FATAL: Cannot write to directory '$( dirname "$COOKIES" )'" ; exit 1; }

# Ensure no broken session caching...
if [[ -s "$COOKIES" ]]; then
	[[ -w "$COOKIES" ]] || { echo >&2 "FATAL: Cannot write to file '$COOKIES'" ; exit 1 ; }
	rm -f "$COOKIES" >/dev/null 2>&1
fi

[[ $DEBUG ]] && echo >&2 "DEBUG: Fetching initial headers to pre-load cookies..."
curl -b $COOKIES -c $COOKIES -Ikso "$DST" -A \"$UA\" --url "$LOGINURL"

[[ $DEBUG ]] && echo >&2 "DEBUG: Fetching UID..."
VALUE="$(
	   curl -b $COOKIES -c $COOKIES -kso - -A \"$UA\" --url "$LOGINURL" | \
	   grep -m 1 "multiform" | \
	   cut -d"'" -f 6
)"

[[ $DEBUG ]] && echo >&2 "DEBUG: Read UID as '$VALUE' - posting data..."
curl -b $COOKIES -c $COOKIES -d "username=$LOGIN" -d "password=$PASSWORD" -d "iov_id" -d "multiform=$VALUE" -e "$LOGINURL" -kso "$DST" -A \"$UA\" --url "$POSTURL"

[[ $DEBUG ]] && echo >&2 "DEBUG: Response received - verifying result..."
curl -b $COOKIES -c $COOKIES -e "$POSTURL" -kso - -A \"$UA\" -H "Accept-Language: $AL" --url "$CHKURL" | \
	   grep -qE "(Welcome|Hi) <b>$LOGIN</b>" \
	&& echo "Login successful" \
	|| { echo >&2 "Login failed" ; mail send -s "Dyndns web login failed !" -f "fritz.box@home.de" -t "\"$EMAIL\" ; exit 1 ; }

exit 0

Leave a ReplyCancel reply

Exit mobile version