What's new

DDNS

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

What address do you lookup? okey your ddns name..........
A DDNS name I have ☺️
Then I search for my public IP address, but not on myip.dnsomatic.com (because they have a hourly limit and sometimes I can't get my external IP address, so I'm using other service).
Then I compare them. If different, update. If the same, do noth
 
The problem is - my wan IP address changed very often (most of times during night), and the DDNS update doesn't start automatically. I have to go and force the update - which isn't the purpose of a DDNS service.
I have set to check it every 30 minutes (minimum allowed) but it simply doesn't update. I saw the logs to check if any error ocurred, but no it simply doesn't trigger a check nor an update.
Maybe it's because I'm behind a double NAT? Is there any way to force an update (or a check) every X minutes using the router's DDNS service?

It probably fails to check because you have the hostname set to all.dnsomatic.com. Try setting it for one of the hostnames you have configured on your account, then check your log for watchdog events calling "start_ddns" in your syslog every configured period of time.
 
It probably fails to check because you have the hostname set to all.dnsomatic.com. Try setting it for one of the hostnames you have configured on your account, then check your log for watchdog events calling "start_ddns" in your syslog every configured period of time.
Ho I see! Didn't think about that I'll give it a try.
Thanks!
 
Well, searching here and there (totally newbie on that language), and with your help, I was able to produce a very simple script that does what I want.

Right now is totally working, but please feel free to clean up the code and teach me good pratices If i'm doing (I know I am) something wrong.

Thanks!
@dave14305

Code:
#!/bin/sh
#DNS-O-MATIC updater
APPNAME=DNSOMatic
USERNAME=username
PASSWORD=password
HOSTNAME=all.dnsomatic.com
DDNS=ddns.wich.gives.current.ip
#vars end


NEWIP="$(curl -fs4 https://api4.my-ip.io/ip)"
if [ -z "$NEWIP" ]; then
  logger -t $APPNAME "MY-IP API returned error, retrying in 25 seconds"
  sleep 25
  NEWIP="$(curl -fs4 https://api4.my-ip.io/ip)"
fi
if [ -z "$NEWIP" ]; then
    logger -t $APPNAME "MY-IP API returned error after retrying, going to DNS-O-Matic API"
    sleep 25
    NEWIP="$(curl -fs4 https://myip.dnsomatic.com/)"
fi
if [ -z "$NEWIP" ]; then
logger -t $APPNAME "Can't get IP Address, stopping..."
exit
fi

CURRENTIP="$(nslookup ${DDNS} | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | awk 'NR>2')"
if [ -z "$CURRENTIP" ]; then
  logger -t $APPNAME "NSLookup returned error, retrying in 25 seconds"
  sleep 25
  CURRENTIP="$(nslookup ${DDNS} | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | awk 'NR>2')"
fi
if [ -z "$CURRENTIP" ]; then
    logger -t $APPNAME "NSLookup returned error after retrying, forcing IP update"
fi

if [ "$NEWIP" != "$CURRENTIP" ]; then
  UPDATE="$(curl -fs4 -k -u "${USERNAME}:${PASSWORD}" "https://updates.dnsomatic.com/nic/update?hostname=${HOSTNAME}&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG&myip=${NEWIP}")"

 if [ "$UPDATE" == "good $NEWIP" ]; then
   if [ -z "$CURRENTIP" ]; then
     logger -t $APPNAME "Forcing IP update to $NEWIP"
   else
     logger -t $APPNAME "Updating IP from $CURRENTIP to $NEWIP"
   fi
 elif [ "$UPDATE" == "abuse" ]; then
   logger -t $APPNAME "Abusing! Nothing updated. Current IP: $CURRENTIP"
 else
   logger -t $APPNAME "Error while updating: \"$UPDATE\". Current IP: $CURRENTIP"
 fi
else
  logger -t $APPNAME "Nothing to update. Current IP: $CURRENTIP"
fi
exit
 
Rather than sleeping you could have curl retry, 7 retries should be about 28 seconds.
https://curl.haxx.se/docs/manpage.html said:
When curl is about to retry a transfer, it will first wait one second and then for all forthcoming retries it will double the waiting time until it reaches 10 minutes which then will be the delay between the rest of the retries

You could also save the IP after a successful update so you don't need to use nslookup to check the previous value.

The other things I'd change would be removing the -k option from curl (you can just use http if you want it to be insecure, and since you're passing credentials it's probably unintentional), equals is only one '=', and wrapping the logger tag with brackets in-case it has a space.

Code:
CACHEFILE='/jffs/config/.ddns.cache'

NEWIP="$(curl -fs4 --retry 7 https://api4.my-ip.io/ip)"
if [ -z "$NEWIP" ]; then
    logger -t "$APPNAME" "Can't get IP Address, stopping..."
else
    read -r CURRENTIP < "$CACHEFILE"

    if [ "$NEWIP" != "$CURRENTIP" ]; then
        UPDATE="$(curl -fs4 -u "${USERNAME}:${PASSWORD}" "https://updates.dnsomatic.com/nic/update?hostname=${HOSTNAME}&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG&myip=${NEWIP}")"

        if [ "$UPDATE" = "good $NEWIP" ]; then
            logger -t "$APPNAME" "Updating IP from $CURRENTIP to $NEWIP"
            echo "$NEWIP" > "$CACHEFILE"
        elif [ "$UPDATE" = "abuse" ]; then
            logger -t "$APPNAME" "Abusing! Nothing updated. Current IP: $CURRENTIP"
        else
            logger -t "$APPNAME" "Error while updating: \"$UPDATE\". Current IP: $CURRENTIP"
        fi
    else
        logger -t "$APPNAME" "Nothing to update. Current IP: $CURRENTIP"
    fi
fi
 
Rather than sleeping you could have curl retry, 7 retries should be about 28 seconds.

You could also save the IP after a successful update so you don't need to use nslookup to check the previous value.

The other things I'd change would be removing the -k option from curl (you can just use http if you want it to be insecure, and since you're passing credentials it's probably unintentional), equals is only one '=', and wrapping the logger tag with brackets in-case it has a space.

Code:
CACHEFILE='/jffs/config/.ddns.cache'

NEWIP="$(curl -fs4 --retry 7 https://api4.my-ip.io/ip)"
if [ -z "$NEWIP" ]; then
    logger -t "$APPNAME" "Can't get IP Address, stopping..."
else
    read -r CURRENTIP < "$CACHEFILE"

    if [ "$NEWIP" != "$CURRENTIP" ]; then
        UPDATE="$(curl -fs4 -u "${USERNAME}:${PASSWORD}" "https://updates.dnsomatic.com/nic/update?hostname=${HOSTNAME}&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG&myip=${NEWIP}")"

        if [ "$UPDATE" = "good $NEWIP" ]; then
            logger -t "$APPNAME" "Updating IP from $CURRENTIP to $NEWIP"
            echo "$NEWIP" > "$CACHEFILE"
        elif [ "$UPDATE" = "abuse" ]; then
            logger -t "$APPNAME" "Abusing! Nothing updated. Current IP: $CURRENTIP"
        else
            logger -t "$APPNAME" "Error while updating: \"$UPDATE\". Current IP: $CURRENTIP"
        fi
    else
        logger -t "$APPNAME" "Nothing to update. Current IP: $CURRENTIP"
    fi
fi
Thanks pal!

As I said, most of it was copy/past/adapt/search, so It was a little messy! Thanks for your help.

Heres the code I have right now:
Code:
if [ "$1" = "init" ]; then
   cru a "$APPNAME" "*/${RUNEACH} * * * * ${0}"
   logger -t "$APPNAME" "Creating cronjob to run every $RUNEACH minutes..."
   logger -t "$APPNAME" "Waiting 120 sec to first update"
   sleep 120
fi
if [ ! -f "$CACHEFILE" ] || [ "$1" = "force" ] || [ "$1" = "init" ]; then
   echo "" > "$CACHEFILE"
fi

if [ -z "$NEWIP" ]; then
    logger -t "$APPNAME" "Can't get IP Address, stopping..."
else
    read -r CURRENTIP < "$CACHEFILE"
    if [ -z "$CURRENTIP" ] && [ -z "$1" ]; then
       logger -t "$APPNAME" "Can't get cached IP, looking up NS"
       CURRENTIP="$(nslookup ${DDNS} | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | awk 'NR>2')"
       echo "$CURRENTIP" > "$CACHEFILE"
    fi
     if [ "$NEWIP" != "$CURRENTIP" ]; then
        UPDATE="$(curl -fs4 -u "${USERNAME}:${PASSWORD}" "https://updates.dnsomatic.com/nic/update?hostname=${HOSTNAME}&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG&myip=${NEWIP}")"
        if [ "$UPDATE" = "good $NEWIP" ]; then
            if [ "$1" = "force" ]; then
               logger -t "$APPNAME" "Forcing IP update to $NEWIP"
            elif [ -z "$CURRENTIP" ] || [ "$1" = "init" ]; then
               logger -t "$APPNAME" "Updating IP to $NEWIP"
            else
               logger -t "$APPNAME" "Updating IP from $CURRENTIP to $NEWIP"
            fi
            echo "$NEWIP" > "$CACHEFILE"
        elif [ "$UPDATE" = "abuse" ]; then
            logger -t "$APPNAME" "Abusing! Nothing updated. Current IP: $CURRENTIP"
        else
            logger -t "$APPNAME" "Error while updating: \"$UPDATE\". Current IP: $CURRENTIP"
        fi
    else
        logger -t "$APPNAME" "Nothing to update. Current IP: $CURRENTIP"
    fi
fi
Then, on services-start, I call it by using
Code:
/jffs/scripts/dnsomatic init

The NSLookup is only a backup if something goes wrong. Probably, it'll never be used.

I have some questions that I can't find answer googling it:
- What's the -fs4 on curl?
- What's the -u on curl?
- What's the difference on equals between = and ==? And if i was doing it wrong, why was it working? :p
- Why is -t needed on logger?
- I don't want it, but let's suppose that in that line if [ -z "$CURRENTIP" ] && [ "$1" != "force" ] && [ "$1" != "init" ]; then i wanted (currentip = "" AND $1 != force) OR $1 = init. May i use:
Code:
if [[ -z "$CURRENTIP" ] && [ "$1" != "force" ]] || [ "$1" != "init" ]; then
?

Thanks once again!!!!
 
You can see the curl options here. -f and -s stop it from showing anything other than the result, and -4 limits it to IPv4. There isn't really any point having -4 with the dnsomatic update, but it's useful for getting your IP from a dual stack service like https://api.my-ip.io/ip. -u is for credentials, which is why the username/password follow.

The reason == works is likely because the busybox ash implementation adds a bunch of extra features over the posix standard, they either copied the syntax from bash or figured enough people would make the mistake that they might as well make it work.

-t on the logger just gives it a nice name in the log. You can use the command "logger --help" in ssh to see the other options, or even just play around with it there "logger -t test testing" will show up in the webui's log.

Getting logical operators to work in the right order is a little cumbersome, you can use {} for it but spaces/semicolons need to be right.
Code:
if { [ -z "$CURRENTIP" ] && [ "$1" != "force" ]; } || [ "$1" != "init" ]; then
 
You can see the curl options here. -f and -s stop it from showing anything other than the result, and -4 limits it to IPv4. There isn't really any point having -4 with the dnsomatic update, but it's useful for getting your IP from a dual stack service like https://api.my-ip.io/ip. -u is for credentials, which is why the username/password follow.

The reason == works is likely because the busybox ash implementation adds a bunch of extra features over the posix standard, they either copied the syntax from bash or figured enough people would make the mistake that they might as well make it work.

-t on the logger just gives it a nice name in the log. You can use the command "logger --help" in ssh to see the other options, or even just play around with it there "logger -t test testing" will show up in the webui's log.

Getting logical operators to work in the right order is a little cumbersome, you can use {} for it but spaces/semicolons need to be right.
Code:
if { [ -z "$CURRENTIP" ] && [ "$1" != "force" ]; } || [ "$1" != "init" ]; then

Perfect, thanks for all explanations!
Excited... :)
 
You can see the curl options here. -f and -s stop it from showing anything other than the result, and -4 limits it to IPv4. There isn't really any point having -4 with the dnsomatic update, but it's useful for getting your IP from a dual stack service like https://api.my-ip.io/ip. -u is for credentials, which is why the username/password follow.

The reason == works is likely because the busybox ash implementation adds a bunch of extra features over the posix standard, they either copied the syntax from bash or figured enough people would make the mistake that they might as well make it work.

-t on the logger just gives it a nice name in the log. You can use the command "logger --help" in ssh to see the other options, or even just play around with it there "logger -t test testing" will show up in the webui's log.

Getting logical operators to work in the right order is a little cumbersome, you can use {} for it but spaces/semicolons need to be right.
Code:
if { [ -z "$CURRENTIP" ] && [ "$1" != "force" ]; } || [ "$1" != "init" ]; then
Just one more question!
Instead of getting the text from that url with curl, what do I have to do if I want to download the page? Will I also use CURL?
Because I thought that curl was for downloading webpages, not to getting their content as text
 

Similar threads

Latest threads

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top