Comprehensive IPv6 framework with support for freedns. #40

Open
wants to merge 12 commits into
from

Conversation

Projects
None yet
4 participants

dkerr64 commented Mar 18, 2016

Updates here are based on work I have done for the AstLinux project (AstLinux.org)

Adding comprehensive framework for IPv6 support. IPv6 and IPv4 exist side-by-side
The same network interface may have both IPv4 and IPv6. Therefore to support both
we add the following options.

usev6 = [ ip, if, cmd, web ]
ipv6 = [ set an IPv6 address (usev6=ip) ]
webv6 = [ url of a web server that will return your IPv6 address (usev6=web)]
webv6-skip = [ string to skip to before looking for IPv6 address]
cmdv6 = [ system command to execute that will return an IPv6 address (usev6=cmd)]
cmdv6-skip = [ string to skip to before looking for IPv6 address ]

There is no ifv6. It is assumed that if=interface will be the same for both IPv4
and IPv6

You can mix methods for IPv4 and IPv6 for the same interface. For example
use=web
usev6=if
if=eth0
web=http://ipdetect.dnspark.com/
Would be a valid method for a system behind an IPv4 NAT connection, IPv6 would be
obtained from the eth0 interface (globaly routable address) and the public IPv4
from external web site.

Support for updating AAAA (IPv6) records is added for freedns.afraid.org. The
existing IPv6 nsupdate method was updated to account for new design.

Optional support is added for cURL as some embedded systems do not have perl
NET6 and SSL packages installed. Set with option
curl=yes

Submitted code is ready for code review and comment.

Updates here are based on work I have done for the AstLinux project (…
…AstLinux.org)

Adding comprehensive framework for IPv6 support.  IPv6 and IPv4 exist side-by-side
The same network interface may have both IPv4 and IPv6.  Therefore to support both
we add the following options.

 usev6 = [ ip, if, cmd, web ]
 ipv6 = [ set an IPv6 address (usev6=ip) ]
 webv6 = [ url of a web server that will return your IPv6 address (usev6=web)]
 webv6-skip = [ string to skip to before looking for IPv6 address]
 cmdv6 = [ system command to execute that will return an IPv6 address (usev6=cmd)]
 cmdv6-skip = [ string to skip to before looking for IPv6 address ]

There is no ifv6. It is assumed that if=interface will be the same for both IPv4
and IPv6

You can mix methods for IPv4 and IPv6 for the same interface.  For example
 use=web
 usev6=if
 if=eth0
 web=http://ipdetect.dnspark.com/
Would be a valid method for a system behind an IPv4 NAT connection, IPv6 would be
obtained from the eth0 interface (globaly routable address) and the public IPv4
from external web site.

Support for updating AAAA (IPv6) records is added for freedns.afraid.org.  The
existing IPv6 nsupdate method was updated to account for new design.

Optional support is added for cURL as some embedded systems do not have perl
NET6 and SSL packages installed.  Set with option
 curl=yes

Submitted code is ready for code review and comment.

@dkerr64 dkerr64 changed the title from Updates here are based on work I have done for the AstLinux project (… to Comprehensive IPv6 framework with support for freedns. Mar 18, 2016

ddclient
+ $reply = `/usr/bin/curl -si0 --user "${login}:${password}" --user-agent "${program}/${version}" \\
+ --connect-timeout $timeout --max-time $timeout $curlopt \\
+ --url "${protocol}://${server}/${url}" 2>/dev/null`;
+
@abelbeck

abelbeck Mar 18, 2016

Contributor

Excellent idea to optionally use curl as it is ubiquitous, performs either IPv4/IPv6 and SSL all in one call.

But, may I suggest you use "HERE Documents" to minimize unwanted special-character processing:

    $reply = <<`USE_CURL`;
/usr/bin/curl -si0 --user '${login}:${password}' --user-agent '${program}/${version}' \\
      --connect-timeout $timeout --max-time $timeout $curlopt \\
      --url '${protocol}://${server}/${url}' 2>/dev/null
USE_CURL

Also use singe-quotes around the string arguments, better to allow ${password} special characters and does not effect the ${foo} perl replacement.

dkerr64 commented Mar 18, 2016

Lonnie, thanks for the comments. I am not familiar with the HERE Documents method but based on your comments it does look like being a good idea.

Thanks

dkerr64 commented Mar 18, 2016

Further testing has revealed that the Perl built-in NET6 support is not a reliable method. While it works fine if you are on a system that is IPv6 connected, it is failing in some cases if you try and use it on a system that is only IPv4. ie, running "ddclient -query" fails half way through testing webv6 sites if you are on a system that is not currently connected IPv6. It simply crashes with no diag info on the syswrite command ..
my $result = syswrite $sd, $rq;

One argument would of course be that you simply shouldn't do that... use INET6 on a system not IPv6 enabled. But a simpler approach might just be to enforce use of Curl when IPv6 is requested.

David

dkerr64 added some commits Mar 18, 2016

Force use of cURL when IPv6 protocol requested. The Perl NET6 functio…
…ns do not fail

gracefully or fall back on IPv4 when running on a system that is not connected to IPv6
network.  Result is that ddclient may crash if IPv6 requested on a system that doesn't
have IPv6.

dkerr64 added some commits Jul 2, 2016

Fixed bug that would cause IPv4 address to be updated even if it was …
…unchanged.

Caused by testing for IPv6 address change even though no IPv6 update was requested.
Added capability to specify whether IPv4 or IPv6 should be updated or not with new
values:
use=no
usev6=no

andig commented Oct 29, 2016

Whats the status of IPv6 support? I have a small raspi with a global IPv6 address that I'd like to tie to my domain?

dkerr64 commented Oct 29, 2016

@andig I am using the IPv6 support I added with freedns.afraid.org and it is working fine. I use it on two systems... my gateway, which obtains the IPv6 address from the ethernet interface and I use it on an internal server (behind IPv4 NAT) which obtains IPv6 addresses for several internal servers and updates them to freedns (if you want the outside world to get to those servers then you also need to add appropriate firewall rules to the gateway).

However it works only with the freedns service. I have not and don't plan to try and make it work with any other service. I leave that to someone else.

@wimpunk has not commented on the changes I submitted and has not merged into the master. I would very much like it merged but that is not up to me. I would highly recommend a thorough code review -- there are a lot of code changes and as you can see from the commit history I'm not perfect... there have been bugs that I found and corrected. So, I am keen for other eyes to look this over.

Thanks your interest and support.

dak.

dkerr64 commented Oct 29, 2016

by-the-way.... in the above post I stated that I have one server that obtains IPv6 addresses for other servers on my internal network and updates the address to freedns. How do I do that? With the following ugly cmdv6= in ddclient.conf...

usev6=cmd
cmdv6="{ host=qnap; ping $host -c 1 >/dev/null; ipv6=$(ip addr show dev ens3 | grep \"scope.global\" | sed -e's/^.*inet6 \\([^ ]*\\)\\/.*$/\\1/;t;d'); mac=$(arp -a $host | sed -e's/^.* at \\([^ ]*\\) .*$/\\1/;t;d'); ipv6calc -q --in prefix+mac --action prefixmac2ipv6 --out ipv6addr  $ipv6 $mac 2>/dev/null; }"

In this case the internal server has a hostname of "qnap"
If you want to try this on a command line then be sure to remove the backslash's before the quotes and backlashes. In other words...

{ host=qnap; ping $host -c 1 >/dev/null; ipv6=$(ip addr show dev ens3 | grep "scope.global" | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'); mac=$(arp -a $host | sed -e's/^.* at \([^ ]*\) .*$/\1/;t;d'); ipv6calc -q --in prefix+mac --action prefixmac2ipv6 --out ipv6addr $ipv6 $mac 2>/dev/null; }

Try that from your linux cmd line (substitute valid local host name for qnap) !
You may need to sudo apt install some of the ipv6 utilities. This works on Ubuntu.

dak

Collaborator

wimpunk commented Nov 2, 2016

Sorry I missed this one... I'll try to take a review asap.
Did anyone tried the patch already?

@wimpunk wimpunk self-assigned this Nov 2, 2016

@wimpunk wimpunk added the enhancement label Nov 2, 2016

Collaborator

wimpunk commented Feb 15, 2017

Seems like there are issues when trying to merge and I have some reviews which didn't got any respons. Can you review them?

dkerr64 commented Feb 16, 2017

Working on re-syncing with your current master, don't merge until I complete and test please. I'll let you know once that is done.
Please point me at the review/comments that I have not responded to.

Collaborator

wimpunk commented Feb 16, 2017

About the comments: there was a load_ssl_support removed from line 1981 and the identification changed. I argued that I'm aware of a bad indentation but there is no need to correct it on rows you didn't change the contents on.

dkerr64 commented Feb 16, 2017

I have fixed all the white space diffs.

@@ -1991,74 +2091,67 @@ sub geturl {
if ( $force_ssl || ($globals{'ssl'} and (caller(1))[3] ne 'main::get_ip') ) {
$use_ssl = 1;
$default_port = 443;
- load_ssl_support;
@dkerr64

dkerr64 Feb 16, 2017

This load_ssl_support is deleted here and moved down to where it is needed. IPv6 only works with cURL so this should be loaded only if required for IPv4 and only if cURL is not being used for HTTP.

+ debug("skipped network connection");
+ verbose("SENDING:", "%s", $request);
+ } elsif ($use_ssl) {
+ load_ssl_support;
@dkerr64

dkerr64 Feb 16, 2017

load_ssl_support moved here... where required.

dkerr64 commented Feb 16, 2017

load_ssl_support was moved lower into the code. See inline comments.

dkerr64 commented Feb 16, 2017

An additional comment on load_ssl_support. We ran into several problems using the perl IO::Socket with IPv6 and SSL eventually I had to abandon using it and so if you use IPv6 in ddclient (this pull request) then you need to use cURL... which has to be enabled in the .conf file -- which enables it for both IPv6 and IPv4. After further review we decided to abandon IO:Socket completely and for the astinux-project pulled all the code out of ddclient in our own fork (https://github.com/astlinux-project/ddclient-curl). cURL is much more robust and portable across systems and has proven much more stable. With this pull request I have had to weave in IPv6 support using cURL without breaking any of your existing IPv4 code that uses IO:Socket making the end result more complicated than it need be.

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