From e35aa941e129a3bb5bfb70de8e732b1a1b6923f3 Mon Sep 17 00:00:00 2001 From: troyengel Date: Sat, 16 Sep 2017 10:22:07 -0500 Subject: [PATCH 1/4] implement v2 API, fixes #5 --- README.pod | 7 +++++++ petrified | 8 ++++---- petrified.1 | 33 +++++++++++++++++++-------------- petrified.conf | 8 ++++---- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/README.pod b/README.pod index eaa5948..1ce2f96 100644 --- a/README.pod +++ b/README.pod @@ -13,6 +13,13 @@ L; the software goals are for simplicity, flexibility and configurability while using the minimal system tools installed with most distributions. + Version 1.x = FreeDNS API v1 + Version 2.x = FreeDNS API v2 + +If upgrading from API v1 to v2, a manual action is required on the +FreeDNS website to generate a new API key for each domain name. See +L for more information. + =head1 OPTIONS =over 4 diff --git a/petrified b/petrified index eeffe30..b87f0e6 100755 --- a/petrified +++ b/petrified @@ -2,7 +2,7 @@ # ## petrified - bash client to update dynamic DNS at freedns.afraid.org ## Copyright (c) 2015 Troy Engel -## Version: 1.0.6 +## Version: 2.0.0 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -37,8 +37,8 @@ while getopts ":c:" opt; do esac done -## How to update DNS - DDNS_KEY is unique per domain -DDNS_URL=https://freedns.afraid.org/dynamic/update.php +## v2 API - How to update DNS - DDNS_KEY is unique per domain +DDNS_URL=https://sync.afraid.org/u/ DDNS_KEY="" ## Which URL to use to get an IP @@ -215,7 +215,7 @@ fi # If they don't match, tell upstream if [[ "${OLDIP}" != "${NEWIP}" ]]; then - UPDURL="${DDNS_URL}?${DDNS_KEY}&address=${NEWIP}" + UPDURL="${DDNS_URL}${DDNS_KEY}/?ip=${NEWIP}" RESULT=$(curl -m ${CURL_WAIT} -sk "${UPDURL}" 2>/dev/null) logmsg "${RESULT}" else diff --git a/petrified.1 b/petrified.1 index d3f8b43..9285d2c 100644 --- a/petrified.1 +++ b/petrified.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) +.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,7 +46,7 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" -.\" If the F register is turned on, we'll generate index entries on stderr for +.\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. @@ -54,20 +54,16 @@ .\" Avoid warning from groff about undefined register 'F'. .de IX .. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" +.if !\nF .nr F 0 +.if \nF>0 \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" .. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 . \} .\} -.rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -133,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "PETRIFIED 1" -.TH PETRIFIED 1 "2016-01-24" "petrified 1.0.6" "Petrified Manual" +.TH PETRIFIED 1 "2017-09-16" "petrified 2.0.0" "Petrified Manual" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -149,6 +145,15 @@ Usage: \fBpetrified\fR [ \fB\-c\fR \fIconfig\fR ] ; the software goals are for simplicity, flexibility and configurability while using the minimal system tools installed with most distributions. +.PP +.Vb 2 +\& Version 1.x = FreeDNS API v1 +\& Version 2.x = FreeDNS API v2 +.Ve +.PP +If upgrading from \s-1API\s0 v1 to v2, a manual action is required on the +FreeDNS website to generate a new \s-1API\s0 key for each domain name. See + for more information. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-c\fR \fIconfig\fR" 4 diff --git a/petrified.conf b/petrified.conf index 45b450b..cd15ef1 100644 --- a/petrified.conf +++ b/petrified.conf @@ -14,11 +14,11 @@ # This is the unique string for the dynamic DNS entry to update; visit -# http://freedns.afraid.org/dynamic/ - next to the DNS entries towards -# the bottom is a link "Direct URL"; copy that and extract the string -# after the '...update.php?' part and put here. +# https://freedns.afraid.org/dynamic/v2/ - next to the DNS entries towards +# the bottom is a link to sync.afraid.org; copy that and extract the string +# after the '.../u/' part and put here. # -# Example: DDNS_KEY=9C4yjq3kaekkYNbYsKRqcosTmouMYbfVMLkJtR== +# Example: DDNS_KEY=ZIfSWnXKuDqMpNEsTXBA852 DDNS_KEY= # Which URL to use to get an IP - the expectation is output from this From 3ea1f3e3b28cb84d1832fad1e77f6f0792fd78d6 Mon Sep 17 00:00:00 2001 From: troyengel Date: Sat, 16 Sep 2017 10:58:08 -0500 Subject: [PATCH 2/4] LOG_QUIET, result checking, partially fixes #4 --- petrified | 18 ++++++++++++++++-- petrified.conf | 4 ++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/petrified b/petrified index b87f0e6..def24f3 100755 --- a/petrified +++ b/petrified @@ -65,6 +65,9 @@ USE_SYSLOG=0 USE_STDOUT=0 USE_LOGFILE=0 +## If set, does not log if the IP has not changed +LOG_QUIET=0 + ## If USE_LOGFILE is 1, where to log PET_LOG=/var/log/petrified.log @@ -214,16 +217,27 @@ if (( ${USE_LIP} == 1 )); then fi # If they don't match, tell upstream +__UPDATED=0 if [[ "${OLDIP}" != "${NEWIP}" ]]; then UPDURL="${DDNS_URL}${DDNS_KEY}/?ip=${NEWIP}" RESULT=$(curl -m ${CURL_WAIT} -sk "${UPDURL}" 2>/dev/null) logmsg "${RESULT}" + # "Updated foo from 1.2.3.4 to 5.6.7.8" + # "No IP change detected for foo with IP 1.2.3.4, skipping update" + _RE1='^Updated' + _RE2='^No IP change detected' + if [[ ${RESULT} =~ ${_RE1} ]] || [[ ${RESULT} =~ ${_RE2} ]]; then + # if _RE2 matched, our PET_LIP is stale + __UPDATED=1 + fi else - logmsg "IP ${NEWIP} hasn't changed, not updating." + if (( ${LOG_QUIET} == 0 )); then + logmsg "IP ${NEWIP} hasn't changed, not updating." + fi fi # Save the new IP if configured -if (( ${USE_LIP} == 1 )); then +if (( ${USE_LIP} == 1 )) && (( ${__UPDATED} == 1 )); then if (( $(touch "${PET_LIP}" 2>/dev/null; echo $?;) != 0 )); then logmsg "USE_LIP=1 but cannot write to ${PET_LIP}." else diff --git a/petrified.conf b/petrified.conf index cd15ef1..a5ac4ad 100644 --- a/petrified.conf +++ b/petrified.conf @@ -56,6 +56,10 @@ DDNS_CHECK="http://4.icanhazip.com" #USE_STDOUT=0 #USE_LOGFILE=0 +# If set, does not log if the IP has not changed {0,1} +# +#LOG_QUIET=0 + # If USE_LOGFILE is 1, where to log {} # #PET_LOG=/var/log/petrified.log From 6c08ad807c3c4cd039eca813175f314e740bab8e Mon Sep 17 00:00:00 2001 From: troyengel Date: Fri, 29 Sep 2017 09:43:35 -0500 Subject: [PATCH 3/4] shebang change for portability --- petrified | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/petrified b/petrified index def24f3..f5ff1ee 100755 --- a/petrified +++ b/petrified @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # ## petrified - bash client to update dynamic DNS at freedns.afraid.org ## Copyright (c) 2015 Troy Engel From de91e17240953a2f24f607ca418a6ec9d81e04a1 Mon Sep 17 00:00:00 2001 From: troyengel Date: Fri, 29 Sep 2017 10:20:01 -0500 Subject: [PATCH 4/4] autodetect API by length of API key --- README.pod | 8 +++++--- petrified | 35 +++++++++++++++++++++++++++++++++-- petrified.1 | 12 ++++++------ petrified.conf | 22 +++++++++++++++++----- 4 files changed, 61 insertions(+), 16 deletions(-) diff --git a/README.pod b/README.pod index 1ce2f96..cbef50e 100644 --- a/README.pod +++ b/README.pod @@ -13,13 +13,15 @@ L; the software goals are for simplicity, flexibility and configurability while using the minimal system tools installed with most distributions. - Version 1.x = FreeDNS API v1 - Version 2.x = FreeDNS API v2 - If upgrading from API v1 to v2, a manual action is required on the FreeDNS website to generate a new API key for each domain name. See L for more information. +By default, petrified will use the length of the API key to automatically +choose the APIv1 or APIv2 URL; this can be overridden in the configuration +file to force a specific version, as the v1 key length is variable but the +v2 key length is fixed at 24 chars. + =head1 OPTIONS =over 4 diff --git a/petrified b/petrified index f5ff1ee..77fccf2 100755 --- a/petrified +++ b/petrified @@ -38,9 +38,18 @@ while getopts ":c:" opt; do done ## v2 API - How to update DNS - DDNS_KEY is unique per domain -DDNS_URL=https://sync.afraid.org/u/ +DDNS_URL="" DDNS_KEY="" +## From Josh, v1 key is variable but v2 is fixed length @24char. When set +## to 0 (auto) the length of the DDNS_KEY will be used to choose which API +## endpoint, otherwise specify 1 (API v1) or 2 (API v2) directly +DDNS_API=0 + +## API URL endpoints, no trailing slashes +DDNS_V1U=https://freedns.afraid.org/dynamic/update.php +DDNS_V2U=https://sync.afraid.org/u + ## Which URL to use to get an IP # IPv4 icanhazip (http://major.io/icanhazip-com-faq/) DDNS_CHECK="http://4.icanhazip.com" @@ -106,6 +115,28 @@ fi if [[ -z "${DDNS_KEY}" ]]; then echo "DDNS_KEY must be configured, exiting." exit 1 +else + # Set the API version endpoint, IP added later + case ${DDNS_API} in + 0) + # From Josh, v2 is fixed @24 but v1 is variable (typically >24) + if [[ ${#DDNS_KEY} -ne 24 ]]; then + DDNS_URL="${DDNS_V1U}?${DDNS_KEY}&address=" + else + DDNS_URL="${DDNS_V2U}/${DDNS_KEY}/?ip=" + fi + ;; + 1) + DDNS_URL="${DDNS_V1U}?${DDNS_KEY}&address=" + ;; + 2) + DDNS_URL="${DDNS_V2U}/${DDNS_KEY}/?ip=" + ;; + *) + echo "DDNS_API must be 0, 1 or 2; exiting." + exit 1 + ;; + esac fi # Make sure that PET_LOG will work if required @@ -219,7 +250,7 @@ fi # If they don't match, tell upstream __UPDATED=0 if [[ "${OLDIP}" != "${NEWIP}" ]]; then - UPDURL="${DDNS_URL}${DDNS_KEY}/?ip=${NEWIP}" + UPDURL="${DDNS_URL}${NEWIP}" RESULT=$(curl -m ${CURL_WAIT} -sk "${UPDURL}" 2>/dev/null) logmsg "${RESULT}" # "Updated foo from 1.2.3.4 to 5.6.7.8" diff --git a/petrified.1 b/petrified.1 index 9285d2c..2aaff62 100644 --- a/petrified.1 +++ b/petrified.1 @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "PETRIFIED 1" -.TH PETRIFIED 1 "2017-09-16" "petrified 2.0.0" "Petrified Manual" +.TH PETRIFIED 1 "2017-09-29" "petrified 2.0.0" "Petrified Manual" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -146,14 +146,14 @@ Usage: \fBpetrified\fR [ \fB\-c\fR \fIconfig\fR ] flexibility and configurability while using the minimal system tools installed with most distributions. .PP -.Vb 2 -\& Version 1.x = FreeDNS API v1 -\& Version 2.x = FreeDNS API v2 -.Ve -.PP If upgrading from \s-1API\s0 v1 to v2, a manual action is required on the FreeDNS website to generate a new \s-1API\s0 key for each domain name. See for more information. +.PP +By default, petrified will use the length of the \s-1API\s0 key to automatically +choose the APIv1 or APIv2 \s-1URL\s0; this can be overridden in the configuration +file to force a specific version, as the v1 key length is variable but the +v2 key length is fixed at 24 chars. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-c\fR \fIconfig\fR" 4 diff --git a/petrified.conf b/petrified.conf index a5ac4ad..ad689c2 100644 --- a/petrified.conf +++ b/petrified.conf @@ -13,14 +13,26 @@ # See petrified.crontab for examples on how to run via cron/fcron. -# This is the unique string for the dynamic DNS entry to update; visit -# https://freedns.afraid.org/dynamic/v2/ - next to the DNS entries towards -# the bottom is a link to sync.afraid.org; copy that and extract the string -# after the '.../u/' part and put here. +# This is the unique key for the dynamic DNS entry to update; visit: +# https://freedns.afraid.org/dynamic/ (v1 API) or +# https://freedns.afraid.org/dynamic/v2/ (v2 API) +# Next to the DNS entries towards the bottom is a link to afraid.org; +# copy that and extract the string and put here, this is your API key. # -# Example: DDNS_KEY=ZIfSWnXKuDqMpNEsTXBA852 +# Example v1: DDNS_KEY=9C4yjq3kaekkYNbYsKRqcosTmouMYbfVMLkJtR== +# Example v2: DDNS_KEY=ZIfSWnXKuDqMpNEsTXBA852 DDNS_KEY= +# The migration from API v1 to API v2 requires the user to visit the +# website and click a few buttons to generate a new API key for each +# domain; the API v1 length is variable but API v2 is a fixed length +# at 24 chars. This setting will try and autodetect the API version by +# the length of DDNS_KEY - if 24, use v2 else use v1. +# 0 = auto +# 1 = force API v1 +# 2 = force API v2 +DDNS_API=0 + # Which URL to use to get an IP - the expectation is output from this # host in plain text, just the IP - no parsing will be done. The # icanhazip service returns the IPv4 and IPv6 nice and clean.