From 4b4f8187efb5ad63e7e253a094443a1a97d45b48 Mon Sep 17 00:00:00 2001 From: Matthias Dellweg <2500@gmx.de> Date: Sun, 8 Nov 2020 16:02:23 +0100 Subject: [PATCH] Enable dynamicdns module to handle IPv6 Signed-off-by: Matthias Dellweg <2500@gmx.de> Reviewed-by: James Valleroy --- actions/dynamicdns | 44 +++++++++++++++---- plinth/modules/dynamicdns/__init__.py | 5 +++ plinth/modules/dynamicdns/forms.py | 4 ++ .../modules/dynamicdns/static/dynamicdns.js | 3 ++ plinth/modules/dynamicdns/views.py | 6 ++- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/actions/dynamicdns b/actions/dynamicdns index f391f2e54..9e19b38a7 100755 --- a/actions/dynamicdns +++ b/actions/dynamicdns @@ -22,7 +22,7 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # static values WGET=$(which wget) -WGETOPTIONS="-4 -o /dev/null -t 3 -T 3" +WGETOPTIONS="-o /dev/null -t 3 -T 3" EMPTYSTRING="none" NOIP="0.0.0.0" # how often do we poll for IP changes if we are behind a NAT? @@ -51,8 +51,9 @@ doGetOpt() { basicauth=0 ignoreCertError=0 + useIPv6=0 - while getopts ":s:d:u:P:I:U:c:b:p" opt; do + while getopts ":s:d:u:P:I:U:c:b:6:p" opt; do case ${opt} in s) if [ "${OPTARG}" != "${EMPTYSTRING}" ];then @@ -95,6 +96,9 @@ doGetOpt() c) ignoreCertError=${OPTARG} ;; + 6) + useIPv6=${OPTARG} + ;; \?) echo "Invalid option: -${OPTARG}" >&2 exit 1 @@ -137,6 +141,7 @@ doWriteCFG() echo "POSTURL ${updateurl}" echo "POSTAUTH ${basicauth}" echo "POSTSSLIGNORE ${ignoreCertError}" + echo "POSTUSEIPV6 ${useIPv6}" } > ${HELPERCFG} # check if we are behind a NAT Router @@ -187,6 +192,7 @@ doReadCFG() updateurl=$(grep POSTURL "${HELPERCFG}" 2> /dev/null |awk '{print $2}' |grep -v ^\'\') basicauth=$(grep POSTAUTH "${HELPERCFG}" 2> /dev/null |awk '{print $2}' |grep -v ^\'\') ignoreCertError=$(grep POSTSSLIGNORE "${HELPERCFG}" 2> /dev/null |awk '{print $2}' |grep -v ^\'\') + useIPv6=$(grep POSTUSEIPV6 "${HELPERCFG}" 2> /dev/null |awk '{print $2}' |grep -v ^\'\') fi } @@ -259,6 +265,11 @@ doStatus() else echo "${DISABLED_STRING}" fi + if [ ! -z "${useIPv6}" ];then + echo "${useIPv6}" + else + echo "${DISABLED_STRING}" + fi } # ask a public WEB Server for the WAN IP we are comming from @@ -266,11 +277,18 @@ doStatus() doGetWANIP() { if [ ! -z "${ipurl}" ];then - outfile=$(mktemp) - local cmd="${WGET} ${WGETOPTIONS} -O ${outfile} ${ipurl}" - $cmd - wanip=$(sed s/[^0-9.]//g "${outfile}") - rm "${outfile}" + local wgetoptions="${WGETOPTIONS}" + if [ "${useIPv6}" = "enabled" ];then + wgetoptions="${wgetoptions} -6" + else + wgetoptions="${wgetoptions} -4" + fi + local cmd="${WGET} ${wgetoptions} -O - ${ipurl}" + if [ "${useIPv6}" = "enabled" ];then + wanip=$($cmd | tr A-F a-f | sed s/[^0-9a-f:]//g) + else + wanip=$($cmd | sed s/[^0-9.]//g) + fi [ -z "${wanip}" ] && wanip=${NOIP} else # no WAN IP found because of missing check URL @@ -282,7 +300,11 @@ doGetWANIP() # this function is called via cronjob doUpdate() { - local dnsentry=$(nslookup "${host}"|tail -n2|grep A|sed s/[^0-9.]//g) + if [ "${useIPv6}" = "enabled" ];then + local dnsentry="$(host -t AAAA "${host}" | sed 's/.*address\s*//')" + else + local dnsentry="$(host -t A "${host}" | sed 's/.*address\s*//')" + fi if [ "${dnsentry}" = "${wanip}" ];then return fi @@ -297,6 +319,11 @@ doUpdate() if [ "${ignoreCertError}" = "enabled" ];then WGETOPTIONS="${WGETOPTIONS} --no-check-certificate " fi + if [ "${useIPv6}" = "enabled" ];then + WGETOPTIONS="${WGETOPTIONS} -6" + else + WGETOPTIONS="${WGETOPTIONS} -4" + fi local cmd="${WGET} -O /dev/null ${WGETOPTIONS} ${updateurl}" $cmd # ToDo: check the returning text from WEB Server. User need to give expected string. @@ -431,6 +458,7 @@ case ${cmd} in echo "-U The update URL (a HTTP GET on this URL will be done)" echo "-c <1|0> disable SSL check on Update URL" echo "-b <1|0> use HTTP basic auth on Update URL" + echo "-6 use IPv6 type address" echo "" echo "update do a one time update" echo "clean delete configuration" diff --git a/plinth/modules/dynamicdns/__init__.py b/plinth/modules/dynamicdns/__init__.py index dc87de12c..8ca124593 100644 --- a/plinth/modules/dynamicdns/__init__.py +++ b/plinth/modules/dynamicdns/__init__.py @@ -157,6 +157,11 @@ def get_status(): else: status['use_http_basic_auth'] = False + if len(details) > 9: + status['use_ipv6'] = (output.split()[9] == 'enabled') + else: + status['use_ipv6'] = False + if not status['dynamicdns_server'] and not status['dynamicdns_update_url']: status['service_type'] = 'GnuDIP' elif not status['dynamicdns_server'] and status['dynamicdns_update_url']: diff --git a/plinth/modules/dynamicdns/forms.py b/plinth/modules/dynamicdns/forms.py index e4344a85a..ed804bab6 100644 --- a/plinth/modules/dynamicdns/forms.py +++ b/plinth/modules/dynamicdns/forms.py @@ -115,6 +115,10 @@ class ConfigureForm(forms.Form): help_text=help_ip_url, validators=[validators.URLValidator(schemes=['http', 'https', 'ftp'])]) + use_ipv6 = forms.BooleanField( + label=ugettext_lazy('Use IPv6 instead of IPv4'), + required=False) + def clean(self): cleaned_data = super(ConfigureForm, self).clean() dynamicdns_secret = cleaned_data.get('dynamicdns_secret') diff --git a/plinth/modules/dynamicdns/static/dynamicdns.js b/plinth/modules/dynamicdns/static/dynamicdns.js index ef351063d..b37d1b100 100644 --- a/plinth/modules/dynamicdns/static/dynamicdns.js +++ b/plinth/modules/dynamicdns/static/dynamicdns.js @@ -116,6 +116,7 @@ $('#id_dynamicdns_update_url').closest('.form-group').hide(); $('#id_disable_SSL_cert_check').closest('.form-group').hide(); $('#id_use_http_basic_auth').closest('.form-group').hide(); + $('#id_use_ipv6').closest('.form-group').hide(); $('#id_dynamicdns_server').closest('.form-group').show(); } @@ -123,6 +124,7 @@ $('#id_dynamicdns_update_url').closest('.form-group').show(); $('#id_disable_SSL_cert_check').closest('.form-group').show(); $('#id_use_http_basic_auth').closest('.form-group').show(); + $('#id_use_ipv6').closest('.form-group').show(); $('#id_dynamicdns_server').closest('.form-group').hide(); } @@ -138,5 +140,6 @@ $('#id_dynamicdns_secret').closest('.form-group').show(); $('#id_showpw').closest('.form-group').show(); $('#id_dynamicdns_ipurl').closest('.form-group').show(); + $('#id_use_ipv6').closest('.form-group').show(); } })(jQuery); diff --git a/plinth/modules/dynamicdns/views.py b/plinth/modules/dynamicdns/views.py index 6b3bd5193..bd13de447 100644 --- a/plinth/modules/dynamicdns/views.py +++ b/plinth/modules/dynamicdns/views.py @@ -118,6 +118,7 @@ def _apply_changes(request, old_status, new_status): if old_status != new_status: disable_ssl_check = "disabled" use_http_basic_auth = "disabled" + use_ipv6 = "disabled" if new_status['disable_SSL_cert_check']: disable_ssl_check = "enabled" @@ -125,13 +126,16 @@ def _apply_changes(request, old_status, new_status): if new_status['use_http_basic_auth']: use_http_basic_auth = "enabled" + if new_status.get('use_ipv6'): + use_ipv6 = "enabled" + _run([ 'configure', '-s', new_status['dynamicdns_server'], '-d', new_status['dynamicdns_domain'], '-u', new_status['dynamicdns_user'], '-p', '-I', new_status['dynamicdns_ipurl'], '-U', new_status['dynamicdns_update_url'], '-c', disable_ssl_check, '-b', - use_http_basic_auth + use_http_basic_auth, '-6', use_ipv6, ], input=new_status['dynamicdns_secret'].encode()) if old_status['enabled']: