Skip to content

Instantly share code, notes, and snippets.

@pgaulon
Last active June 12, 2023 17:51
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pgaulon/3a844a626458f56903d88c5bb1463cc6 to your computer and use it in GitHub Desktop.
Save pgaulon/3a844a626458f56903d88c5bb1463cc6 to your computer and use it in GitHub Desktop.
Dynamic DNS support shell script for freenom.com
#!/bin/bash
#
# settings
#
# login data
freenom_email="main@address"
freenom_passwd="pswd"
# Open DNS management page in your browser.
# URL vs settings:
# https://my.freenom.com/clientarea.php?managedns={freenom_domain_name}&domainid={freenom_domain_id}
freenom_domain_name="domain.name"
freenom_subdomain_name=""
freenom_domain_id="000000000"
#
# main
#
# get current url
current_ip="$(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com 2>/dev/null | tr -d '"')"
log_file="/tmp/$(basename $0)"
if [ "$current_ip" == "" ]; then
echo "[$(date)] Couldn't get current global ip address." >> ${log_file}.log
exit 1
fi
if [ "$(cat ${log_file}.ip 2>/dev/null)" == "$current_ip" ]; then
exit 0
fi
# login
cookie_file=$(mktemp)
loginPage=$(curl --compressed -k -L -c "$cookie_file" \
"https://my.freenom.com/clientarea.php" 2>&1)
token=$(echo "$loginPage" | grep token | grep -o value=".*" | sed 's/value=//g' | sed 's/"//g' | awk '{print $1}')
loginResult=$(curl --compressed -k -L -c "$cookie_file" \
-F "username=$freenom_email" -F "password=$freenom_passwd" -F "token=$token"\
"https://my.freenom.com/dologin.php" 2>&1)
if [ "$(echo -e "$loginResult" | grep "Location: /clientarea.php?incorrect=true")" != "" ]; then
echo "[$(date)] Login failed." >> ${log_file}.log
rm -f $cookie_file
exit 1
fi
# if record does not exists, add new record, else update the first record; records[0]
dnsManagementURL="https://my.freenom.com/clientarea.php?managedns=$freenom_domain_name&domainid=$freenom_domain_id"
dnsManagementPage=$(curl --compressed -k -L -b "$cookie_file" "$dnsManagementURL")
if [ "$(echo "$dnsManagementPage" | grep -F "records[0]")" == "" ]; then
recordKey="addrecord[0]"
dnsAction="add"
else
recordKey="records[0]"
dnsAction="modify"
fi
token=$(echo "$dnsManagementPage" | grep token | grep -o value=".*" | tail -n 1 | sed 's/value=//g' | sed 's/"//g' | awk '{print $1}')
# request add/update DNS record
updateResult=$(curl --compressed -k -L -b "$cookie_file" \
-F "dnsaction=$dnsAction" \
-F "$recordKey[line]=" \
-F "$recordKey[type]=A" \
-F "$recordKey[name]=$freenom_subdomain_name" \
-F "$recordKey[ttl]=14440" \
-F "$recordKey[value]=$current_ip" \
-F "token=$token" \
"$dnsManagementURL" 2>&1)
# logout
curl --compressed -k -b "$cookie_file" "https://my.freenom.com/logout.php" > /dev/null 2>&1
# clean up
rm -f $cookie_file
if [ "$(echo -e "$updateResult" | grep "$current_ip")" == "" ]; then
echo "[$(date)] Update failed." >> ${log_file}.log
echo -e "$updateResult" > ${log_file}.errorUpdateResult.log
exit 1
else
# save ip address
echo -n "$current_ip" > ${log_file}.ip
exit 0
fi
@dr0pd34d
Copy link

dr0pd34d commented Jun 1, 2017

Hello there, just signed up for my own .CF account and you script does not seem to work anymore.
The problem is the login form, which now has its own token, but the curl command line connection cannot be kept alive to send the right token back (CSRF protection), have you already taken a look at it?
I would help out if you need some more information

@dr0pd34d
Copy link

dr0pd34d commented Jun 1, 2017

I have now used the following repo:
https://github.com/maxisoft/Freenom-dns-updater

This works just fine :)

@pgaulon
Copy link
Author

pgaulon commented Jun 4, 2017

Hi @dr0pd34d ,

You are right, there is a token added to the login page. Thanks for the notice!

However it is not used:

  • you can try to remove the input tag with the token from the inspector of your browser
  • you can also use a proxy like BurpSuite to modify the token on the fly

As far as I tested, you can connect when:

  • the token parameter is not present
  • the token parameter is present but empty
  • the token parameter is present and invalid (not the same as provided, containing weird chars)
  • the token parameter is present and valid

From there I think we can safely assume that it is not used. And I could still use this script today, with the last version (I added an A record pointing to 1.1.1.1, ran the script and check that it was changed to my IP).

However I added the code to grab the token and give it back to the dologin page in case it is used in the future:

loginPage=$(curl --compressed -k -L -c "$cookie_file" \                                                                                                                            
    "https://my.freenom.com/clientarea.php" 2>&1)

token=$(echo "$loginPage" | grep token | grep -o value=".*" | sed 's/value=//g' | sed 's/"//g' | awk '{print $1}')

And token=$token is passed to the dologin call.
I also simplified the other token grab for the managedns page, based on this one.

I think I will give a try to the project you linked, it will be less maintenance for me =).

Thank you!

@gerrydoro
Copy link

gerrydoro commented Jun 10, 2017

To get this script working on OpenWRT/LEDE you need:
opkg install bind-tools bash curl
and you need to remove --compressed from all the script.
Tested on Chaos Calmer 15.05.1 and LEDE 17.01.2

@xand79
Copy link

xand79 commented Nov 6, 2017

Seems like all curl-based scripts not working now. I've got empty loginResult. All because of TLS, I think...

@mkorthof
Copy link

@xand79
try adding --referer 'https://my.freenom.com/clientarea.php' to loginResult and updateResult
ill probably create an updated fork soon

@tompointexe
Copy link

Not working

@mkorthof
Copy link

@mvez73
Copy link

mvez73 commented Mar 7, 2020

@mkorthof can you help me installing your script please? I'm new to this and i'm doing it for learning/fun so i'm very noob....

When i run the install it copy the freenom.conf to the "/usr/local/etc" folder but the freenom.sh is not copied to "/usr/local/bin" folder
Can you help me?

Thanks for your help

edit i progress but now i have an error when trying the script with "freenom.sh -l"
Error: Login - token failure (curl error code: 127)

@mkorthof
Copy link

mkorthof commented Mar 7, 2020

Hi,

When i run the install it copy the freenom.conf to the "/usr/local/etc" folder but the freenom.sh is not copied to "/usr/local/bin" folder
Can you help me?

You're right, I forgot to remove an 'echo' so the install action was not actually executed. Just fixed the Makefile.

edit i progress but now i have an error when trying the script with "freenom.sh -l"
Error: Login - token failure (curl error code: 127)

Make sure you set the correct username and password in the conf file (same login as freenom.com).
If you still not get a token you could try enabling debug.
Feel free to create an issue in the tracker if you think you hit a bug.

@mvez73
Copy link

mvez73 commented Mar 7, 2020

Thanks for your help. The email and the password are correct. I changed my password to remove specials characters just in case but no luck...

How do i enable debug?
And for creating an issue, what information do you need?

edit I found something strange. If i try to go to this page "https://api.freenom.com/v2/domain/list" i got a dialog box to log in but it doesn't work. I can't login. Maybe it's the same reason why i got an error with your script...

edit2 It's working now. I found out that curl wasn't installed... Sorry for the inconvenience

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment