{"id":270,"date":"2017-05-20T17:48:45","date_gmt":"2017-05-20T15:48:45","guid":{"rendered":"https:\/\/www.datenreise.de\/en\/?p=270"},"modified":"2018-03-11T16:54:15","modified_gmt":"2018-03-11T14:54:15","slug":"bash-update-script-for-no-ip-com-dyndns","status":"publish","type":"post","link":"https:\/\/www.datenreise.de\/en\/bash-update-script-for-no-ip-com-dyndns\/","title":{"rendered":"Bash: Update-Script for NO-IP.com (DynDNS)"},"content":{"rendered":"<p>In the meantime I have used a large number of Raspberry Pis for measuring and monitoring purposes. Since these usually hang behind Internet connections with dynamic IP, I have been using <a href=\"https:\/\/www.noip.com\" rel=\"nofollow\">no-ip. com<\/a> as a DynDNS service for some time now. However, the Dynamic DNS Update Client (DUC) offered by NO-IP never really worked reliably for me and so I had no access to the Raspberry Pis on a regular basis. I therefore wrote myself a small bash-script for a reliable and fast update of the IP-address. The script is certainly not perfect, but it has been working reliably for months now. <\/p>\n<p>The functionality is quickly explained:<\/p>\n<ul>\n<li>the script uses Cronjob to regularly determine the current IP<\/li>\n<li>the current IP is compared with the cached IP<\/li>\n<li> If the IP has changed, NO-IP is notified by <em>curl<\/em><\/li>\n<li>the newly determined IP is cached for future comparisons<\/li>\n<li>all IP updates and occurred errors are logged<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<hr \/>\n<h4><strong>Difficulty level:<\/strong> <span style=\"color: #4f70c5;\"><i class=\"icon-wrench\"><\/i><\/span><span style=\"color: #cccccc;\"><i class=\"icon-wrench\"><\/i><i class=\"icon-wrench\"><\/i><i class=\"icon-wrench\"><\/i><\/span><\/h4>\n<hr \/>\n<p>As described above, the script uses <em>curl<\/em> to access NO-IP. Curl must therefore be installed first:<\/p>\n<pre>$ sudo apt-get install curl<\/pre>\n<p>The script is then stored under <em>\/usr\/local\/bin\/noip_updater. sh<\/em> and the permissions are adjusted:<\/p>\n<pre>$ sudo nano \/usr\/local\/bin\/noip_updater.sh\r\n$ sudo chmod 700 \/usr\/local\/bin\/noip_updater.sh<\/pre>\n<p>&nbsp;<\/p>\n<h2>Script<\/h2>\n<p>The following content must be copied to the <em>noip_updater. sh<\/em> file and the <em>USERNAME<\/em>, <em>PASSWORD<\/em> and <em>HOST<\/em> variables must be customized:<\/p>\n<pre>\r\n#!\/bin\/bash\r\n<br \/>\r\n# -------------------------------------------------------\r\n# CONFIG\r\n# -------------------------------------------------------\r\nUSERNAME=\"dein-noip-benutzername\"\r\nPASSWORD=\"dein-noip-passwort\"\r\nHOST=\"dein-noip-host.ddns.net\"\r\nLOGFILE=\/var\/log\/noip.log\r\nIPFILE=\/tmp\/current_ip\r\nUSERAGENT=\"Datenreise NOIP Updater\/0.4\"\r\n<br \/>\r\n\r\nif [ ! -e $IPFILE ]; then\r\n    touch $IPFILE\r\n    if [ $? -ne 0 ]; then\r\n        LOGTEXT=\"IP file could not be created.\"\r\n        LOGDATE=\"[$(date +'%d.%m.%Y %H:%M:%S')]\"\r\n        echo \"$LOGDATE $LOGTEXT\" >> $LOGFILE\r\n        exit 1\r\n    fi\r\nelif [ ! -w $IPFILE ]; then\r\n    LOGTEXT=\"IP file is not writable.\"\r\n    LOGDATE=\"[$(date +'%d.%m.%Y %H:%M:%S')]\"\r\n    echo \"$LOGDATE $LOGTEXT\" >> $LOGFILE\r\n    exit 1\r\nfi\r\n<br \/>\r\n\r\n# IP Validator\r\n# http:\/\/www.linuxjournal.com\/content\/validating-ip-address-bash-script\r\nfunction validate_ip() {\r\n    local  ip=$1\r\n    local  stat=1\r\n\r\n    if [[ $ip =~ ^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$ ]]; then\r\n        OIFS=$IFS\r\n        IFS='.'\r\n        ip=($ip)\r\n        IFS=$OIFS\r\n        [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \\\r\n            && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]\r\n        stat=$?\r\n    fi\r\n    return $stat\r\n}\r\n<br \/>\r\n\r\nGET_IP_URLS=( \"http:\/\/icanhazip.com\" \"https:\/\/api.ipify.org\" \"http:\/\/wtfismyip.com\/text\" \"http:\/\/nst.sourceforge.net\/nst\/tools\/ip.php\" )\r\n\r\nfor key in ${!GET_IP_URLS[@]}; do\r\n    NEWIP=$(curl -s ${GET_IP_URLS[$key]} | grep -o '[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}')\r\n\r\n    if validate_ip $NEWIP; then\r\n        break\r\n    elif [ $key -eq $((${#GET_IP_URLS[@]} - 1)) ]; then\r\n        LOGTEXT=\"Could not find current IP. Offline?\"\r\n        LOGDATE=\"[$(date +'%d.%m.%Y %H:%M:%S')]\"\r\n        echo \"$LOGDATE $LOGTEXT\" >> $LOGFILE\r\n        exit 1\r\n    else\r\n        LOGTEXT=\"Got a non-valid IP from ${GET_IP_URLS[$key]}.\"\r\n        LOGDATE=\"[$(date +'%d.%m.%Y %H:%M:%S')]\"\r\n        echo \"$LOGDATE $LOGTEXT\" >> $LOGFILE\r\n    fi\r\ndone\r\n<br \/>\r\n\r\nSTOREDIP=$(cat $IPFILE)\r\n<br \/>\r\nif [ \"$NEWIP\" != \"$STOREDIP\" ]; then\r\n        RESPONSE=$(curl -s -k -u $USERNAME:$PASSWORD --user-agent \"$USERAGENT\" \"https:\/\/dynupdate.no-ip.com\/nic\/update?hostname=$HOST&myip=$NEWIP\")\r\n        RESPONSE=$(echo $RESPONSE | tr -cd \"[:print:]\")\r\n\r\n        RESPONSE_A=$(echo $RESPONSE | awk '{ print $1 }')\r\n        case $RESPONSE_A in\r\n            \"good\")\r\n                RESPONSE_B=$(echo $RESPONSE | awk '{ print $2 }')\r\n                LOGTEXT=\"(good) DNS hostname(s) successfully updated to $RESPONSE_B.\"\r\n                ;;\r\n            \"nochg\")\r\n                RESPONSE_B=$(echo $RESPONSE | awk '{ print $2 }')\r\n                LOGTEXT=\"(nochg) IP address is current: $RESPONSE_B; no update performed.\"\r\n                ;;\r\n            \"nohost\")\r\n                LOGTEXT=\"(nohost) Hostname supplied does not exist under specified account. Revise config file.\"\r\n                ;;\r\n            \"badauth\")\r\n                LOGTEXT=\"(badauth) Invalid username password combination.\"\r\n                ;;\r\n            \"badagent\")\r\n                LOGTEXT=\"(badagent) Client disabled - No-IP is no longer allowing requests from this update script.\"\r\n                ;;\r\n            \"!donator\")\r\n                LOGTEXT=\"(!donator) An update request was sent including a feature that is not available.\"\r\n                ;;\r\n            \"abuse\")\r\n                LOGTEXT=\"(abuse) Username is blocked due to abuse.\"\r\n                ;;\r\n            \"911\")\r\n                LOGTEXT=\"(911) A fatal error on our side such as a database outage. Retry the update in no sooner than 30 minutes.\"\r\n                ;;\r\n            *)\r\n                LOGTEXT=\"(error) Could not understand the response from No-IP. The DNS update server may be down.\"\r\n                ;;\r\n        esac\r\n\r\n        echo $NEWIP > $IPFILE\r\n\r\n        LOGDATE=\"[$(date +'%d.%m.%Y %H:%M:%S')]\"\r\n        echo \"$LOGDATE $LOGTEXT\" >> $LOGFILE\r\nfi\r\n\r\nexit 0\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Cronjob<\/h2>\n<p>To execute the bash script at regular intervals, a cronjob must be created. For this purpose we work on <em>crontab<\/em>:<\/p>\n<pre>$ sudo nano \/etc\/crontab<\/pre>\n<p>At the bottom, the following entry is simply added and the change is saved on the crontab:<\/p>\n<pre># NO-IP update\r\n*\/5 *   * * *   root    \/usr\/local\/bin\/noip_updater.sh<\/pre>\n<p>Then restart the Cron service.<\/p>\n<pre>$ sudo service cron restart<\/pre>\n<div class=\"supportbox\"><p class=\"supporticon\"><i class=\"icon-heart-empty icon-3x\"><\/i><\/p><p class=\"supporttext\"><strong>This article was helpful for you?<\/strong><br \/>Please support Datenreise.de \u2013 Thank you!<\/p><a class=\"supportbtn\" href=\"https:\/\/www.paypal.com\/cgi-bin\/webscr?cmd=_s-xclick&hosted_button_id=6JPY2XDV9QYLA\" target=\"_blank\"><span class=\"btntext\">Donate<\/span><\/a><\/div>\n<hr \/>\n<span id=\"post-ratings-270\" class=\"post-ratings\" data-nonce=\"51bf2383ab\"><p><strong>Rate this Post:<\/strong><br \/>\r\n<img decoding=\"async\" id=\"rating_270_1\" src=\"https:\/\/www.datenreise.de\/en\/wp-content\/plugins\/wp-postratings\/images\/stars\/rating_on.gif\" alt=\"1 Star\" title=\"1 Star\" onmouseover=\"current_rating(270, 1, '1 Star');\" onmouseout=\"ratings_off(4.1, 0, 0);\" onclick=\"rate_post();\" onkeypress=\"rate_post();\" style=\"cursor: pointer; border: 0px;\" \/><img decoding=\"async\" id=\"rating_270_2\" src=\"https:\/\/www.datenreise.de\/en\/wp-content\/plugins\/wp-postratings\/images\/stars\/rating_on.gif\" alt=\"2 Stars\" title=\"2 Stars\" onmouseover=\"current_rating(270, 2, '2 Stars');\" onmouseout=\"ratings_off(4.1, 0, 0);\" onclick=\"rate_post();\" onkeypress=\"rate_post();\" style=\"cursor: pointer; border: 0px;\" \/><img decoding=\"async\" id=\"rating_270_3\" src=\"https:\/\/www.datenreise.de\/en\/wp-content\/plugins\/wp-postratings\/images\/stars\/rating_on.gif\" alt=\"3 Stars\" title=\"3 Stars\" onmouseover=\"current_rating(270, 3, '3 Stars');\" onmouseout=\"ratings_off(4.1, 0, 0);\" onclick=\"rate_post();\" onkeypress=\"rate_post();\" style=\"cursor: pointer; border: 0px;\" \/><img decoding=\"async\" id=\"rating_270_4\" src=\"https:\/\/www.datenreise.de\/en\/wp-content\/plugins\/wp-postratings\/images\/stars\/rating_on.gif\" alt=\"4 Stars\" title=\"4 Stars\" onmouseover=\"current_rating(270, 4, '4 Stars');\" onmouseout=\"ratings_off(4.1, 0, 0);\" onclick=\"rate_post();\" onkeypress=\"rate_post();\" style=\"cursor: pointer; border: 0px;\" \/><img decoding=\"async\" id=\"rating_270_5\" src=\"https:\/\/www.datenreise.de\/en\/wp-content\/plugins\/wp-postratings\/images\/stars\/rating_off.gif\" alt=\"5 Stars\" title=\"5 Stars\" onmouseover=\"current_rating(270, 5, '5 Stars');\" onmouseout=\"ratings_off(4.1, 0, 0);\" onclick=\"rate_post();\" onkeypress=\"rate_post();\" style=\"cursor: pointer; border: 0px;\" \/><br \/>\r\n<span style=\"color:#999\">4.10\/5 (10 votes)<\/span>\r\n<\/p>\r\n<span class=\"hreview-aggregate\">\r\n  <span class=\"item\">\r\n    <span class=\"fn\">Bash: Update-Script for NO-IP.com (DynDNS)<\/span>, \r\n  <\/span>\r\n  <span class=\"rating\">\r\n    <span class=\"average\">4.10<\/span> out of\r\n    <span class=\"best\">5<\/span> based on <span class=\"votes\">10<\/span> ratings\r\n  <\/span>\r\n<\/span><\/span><span id=\"post-ratings-270-loading\" class=\"post-ratings-loading\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.datenreise.de\/en\/wp-content\/plugins\/wp-postratings\/images\/loading.gif\" width=\"16\" height=\"16\" class=\"post-ratings-image\" \/>Loading...<\/span>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the meantime I have used a large number of Raspberry Pis for measuring and monitoring purposes. Since these usually hang behind Internet connections with dynamic IP, I have been using no-ip. com as a DynDNS service for some time&#8230;<\/p>\n","protected":false},"author":1,"featured_media":271,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41,40],"tags":[108,109,7,16,110,49,111,44,48,112,113,74],"class_list":["post-270","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux","category-raspberry-pi","tag-bash","tag-dyndns","tag-howto","tag-instruction","tag-ip-address","tag-linux","tag-no-ip-com","tag-raspberry-pi","tag-raspbian","tag-script","tag-tutorial-shell","tag-update"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/posts\/270","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/comments?post=270"}],"version-history":[{"count":1,"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/posts\/270\/revisions"}],"predecessor-version":[{"id":272,"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/posts\/270\/revisions\/272"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/media\/271"}],"wp:attachment":[{"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/media?parent=270"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/categories?post=270"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.datenreise.de\/en\/wp-json\/wp\/v2\/tags?post=270"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}