
Add a document describing a design for comprehensive IPv6 support. The ddclient maintainers agreed to this design, and it should be used to guide the implementation of full IPv6 support.
16 KiB
Design Doc: IPv6 Support
Author: @rhansen
Date: 2020-06-09
Signed off by:
@SuperSandro2000
Objective
Add full IPv6 support to ddclient, including support for dual-stack systems.
Background
ddclient's current IPv6 support is limited:
- Users can update either an IPv6 record or an IPv4 record for a host, not both.
- If SSL is used for an HTTP request, IPv6 will be used if the
remote host has a AAAA record, even if the user would rather use
IPv4. This breaks
use=web
for IPv4 if theweb
URL's host has a AAAA record. - The
use=if
method only works if the user setsif-skip
to something that skips over all IPv4 addresses in the output ofifconfig
(orip
). If the output contains an IPv4 address after the IPv6 address thenuse=if
cannot be used for IPv6. - There is no support for falling back to IPv4 if an IPv6 connection fails.
use=if
does not filter out locally scoped or temporary IPv6 addresses.
Some attempts have been made to add more robust IPv6 support:
- Debian's ddclient package applies a
patch
that adds a new
usev6
option. Theusev6
option can be set toip
orif
, but not any of the other strategies currently available for theuse
option (web
,cmd
,fw
,cisco
,cisco-asa
). When set toip
orif
, only IPv6 addresses are considered; IPv4 addresses are ignored. The patch does not change the behavior of theuse
option, souse=web
oruse=cmd
can be used for IPv6 if pointed at something that only outputs an IPv6 address. - ddclient-curl is a fork of ddclient that uses curl as the HTTP client (instead of ddclient's own homemade client) for more robust IPv6 support.
- PR #40 is perhaps the most comprehensive attempt at adding full IPv6 support, but it was never merged and has since bit-rotted. There is renewed effort to rebase the changes and get them merged in. PR #40 adds new options and changes some existing options. The approach taken is to completely isolate IPv4 address detection from IPv6 address detection and require the update protocol callbacks to handle each type of address appropriately.
Requirements
- The mechanism for determining the current IPv4 address (the
use
option) must be independently configurable from the mechanism used to determine the current IPv6 address. - The user must be able to disable IPv4 address updates without affecting IPv6 updates.
- The user must be able to disable IPv6 address updates without affecting IPv4 updates.
- If HTTP polling is used for both IPv4 and IPv6 address discovery,
the URL used to determine the IPv4 address (the
web
option) must be independently configurable from the URL used to determine the IPv6 address. - The use of IPv4 or IPv6 to update a record must be independent of the type of record being updated (IPv4 or IPv6).
- The callback for the update protocol must be given both addresses, even if only one of the two addresses has changed.
- The callback for the update protocol must be told which addresses have changed.
- There must be IPv6 equivalents to
use=ip
,use=if
,use=web
, anduse=cmd
. For the IPv6 equivalent touse=if
, it is acceptable to ignore non-global and temporary addresses (the user can always use the IPv6 equivalent touse=cmd
to get non-global or temporary addresses). - Existing support for updating IPv6 records must not be lost.
- Some dynamic DNS service providers use separate credentials for the IPv4 and IPv6 records. These providers must be supported, either by accepting both sets of credentials in a single host's configuration or by allowing the user to specify the same host twice, once for IPv4 and once for IPv6.
Nice-to-Haves
- The user should be able to force the update protocol to use IPv4 or IPv6.
- Unless configured otherwise, ddclient should first attempt to update via IPv6 and fall back to IPv4 if the IPv6 connection fails. This behavior can be added later; for now it is acceptable to keep the current behavior (use IPv6 without IPv4 fallback if there is a AAAA record, use IPv4 if there is no AAAA record).
- Full backwards compatibility with existing config files and flags. The trade-offs between migration burden, long-term usability, and code maintenance should be carefully considered.
- IPv6 equivalents to
use=fw
,use=cisco
, anduse=cisco-asa
. - Add IPv6 support in protocol callbacks where IPv6 support is currently missing. (This can be done later.)
Proposal
Configuration changes
- Add new
usev4
andusev6
settings that are like the currentuse
setting except they only apply to IPv4 and IPv6, respectively.usev4
can be set to one of the following values:disabled
,ipv4
,webv4
,fwv4
,ifv4
,cmdv4
,ciscov4
,cisco-asav4
usev6
can be set to one of the following values:disabled
,ipv6
,webv6
,fwv6
,ifv6
,cmdv6
,ciscov6
,cisco-asav6
- Add a new
use
strategy:disabled
. - The
disabled
value foruse
,usev4
, andusev6
causes ddclient to act as if it was never set. This is useful for overriding the global value for a particular host. - For compatibility with ddclient-curl,
no
is a deprecated alias ofdisabled
. - Add new
ipv4
,ipv6
,webv4
,webv4-skip
,webv6
,webv6-skip
,ifv4
,ifv6
,cmdv4
,cmdv6
, etc. settings that behave like their versionless counterparts except they only apply to IPv4 or IPv6. Deprecate the versionless counterparts, and change their behavior so that they also influence the default value of the versioned options. (Example: Supposeusev4=ifv4
. Ififv4
is not set thenif
is used.) Special notes:- The value of
ip
will only serve as the default foripv4
(oripv6
) if it contains an IPv4 (or IPv6) address. - There is currently an
ipv6
boolean setting. To preserve backward compatibility with existing configs,ipv6
set to a boolean value is ignored (other than a warning). - There is no
ifv4-skip
orifv6-skip
because it's ddclient's responsibility to properly parse the output of whatever tool it uses to read the interface's addresses. - For now there is no
cmdv4-skip
orcmdv6-skip
. Anyone who already knows how to write a regular expression can probably write a wrapper script. These may be added in the future if users request them, especially if it facilitates migration away from the deprecatedcmd-skip
setting. - For
usev6=ifv6
, interfaces are likely to have several IPv6 addresses (unlike IPv4). Choosing the "right" IPv6 address is not trivial. Fortunately, we don't have to solve this perfectly right now; we can choose something that mostly works and let user bug reports guide future refinements. For the first iteration, we will try the following:- Ignore addresses that are not global unicast.
(Unfortunately, the
ip
command from iproute2 does not provide a way to filter out ULA addresses so we will have to do this ourselves.) - Ignore temporary addresses.
- If no addresses remain, log a warning and don't update the IPv6 record.
- Otherwise, if one of the remaining addresses matches the previously selected address, continue to use it.
- Otherwise, select one arbitrarily.
- Ignore addresses that are not global unicast.
(Unfortunately, the
- The value of
- Deprecate the
use
setting (print a loud warning) but keep its existing semantics with an exception: If there is a conflict withusev4
orusev6
then those take priority:- If
use
,usev4
, andusev6
are all set then a warning is logged and theuse
setting is ignored. - If
use
andusev4
are both set and theuse
strategy discovers an IPv4 address that differs from the address discovered by theusev4
strategy, then the address fromusev4
is used and a warning is logged. - If
use
andusev6
are both set and theuse
strategy discovers an IPv6 address that differs from the address discovered by theusev6
strategy, then the address fromusev6
is used and a warning is logged.
- If
- If
usev4
(usev6
) is not set:- If
ipv4
(usev6
) is set, ddclient acts as ifusev4
(usev6
) was set toipv4
(ipv6
). - Otherwise, if
ifv4
(ifv6
) is set, ddclient acts as ifusev4
(usev6
) was set toifv4
(ifv6
). - Otherwise, if
cmdv4
(cmdv6
) is set, ddclient acts as ifusev4
(usev6
) was set tocmdv4
(cmdv6
). - Otherwise, if
fwv4
(fwv6
) is set, ddclient acts as ifusev4
(usev6
) was set tofwv4
(fwv6
). - Otherwise,
usev4
(usev6
) remains unset.
- If
- To support separate credentials for IPv4 vs. IPv6 updates, users can specify the same host multiple times, each time with different options.
Internal API changes
-
Add two new entries to the
$config{$host}
hash:$config{$host}{'wantipv4'}
is set to:- If
usev4
is enabled, the IPv4 address discovered by theusev4
strategy. - Otherwise, if
use
is enabled and theuse
strategy discovered an IPv4 address, the IPv4 address discovered by theuse
strategy. - Otherwise,
undef
.
- If
$config{$host}{'wantipv6'}
is set to:- If
usev6
is enabled, the IPv6 address discovered by theusev6
strategy. - Otherwise, if
use
is enabled and theuse
strategy discovered an IPv6 address, the IPv6 address discovered by theuse
strategy. - Otherwise,
undef
.
- If
-
Deprecate the existing
$config{$host}{'wantip'}
entry, to be removed after all update protocol callbacks have been updated to use the above new entries. In the meantime, this entry's value depends on which ofuse
,usev4
, andusev6
is enabled, and what type of IP address is discovered by theuse
strategy (if enabled), according to the following table:use
usev4
usev6
resulting value ✔(IPv4) ✖ ✖ the IPv4 address discovered by the use
strategy✔(IPv6) ✖ ✖ the IPv6 address discovered by the use
strategy✖ ✔ ✖ the IPv4 address discovered by the usev4
strategy✖ ✖ ✔ the IPv6 address discovered by the usev6
strategy✔(IPv4) ✔ ✖ the IPv4 address discovered by the usev4
strategy (and log another warning if it doesn't match the IPv4 address found by theuse
strategy)✔(IPv6) ✔ ✖ the IPv6 address discovered by the use
strategy✔(IPv4) ✖ ✔ the IPv4 address discovered by the use
strategy✔(IPv6) ✖ ✔ the IPv6 address discovered by the usev6
strategy (and log another warning if it doesn't match the IPv6 address found by theuse
strategy) -
To support separate credentials for IPv4 vs. IPv6 updates, convert the
%config
hash of host configs into a list of host configs. A second definition for the same host adds a second entry rather than overwrites the existing entry.
Alternatives Considered
Repurpose the existing settings for v4
Rather than create new usev4
, ifv4
, cmdv4
, etc. settings,
repurpose the existing use
, if
, cmd
, etc. settings for IPv4.
Why this was rejected:
- There is a usability advantage to the symmetry with the
v6
settings. - It is easier to remain compatible with existing configurations.
Let use
set the default for usev4
Rather than three separate IP discovery mechanisms (use
, usev4
,
and usev6
), have just two (usev4
and usev6
) and let the old
use
setting control the default for usev4
: If usev4
is not set,
then use=foo
is equivalent to usev4=foov4
.
Why this was rejected: Backwards incompatibility. Specifically, configurations that previously updated an IPv6 record would instead (attempt to) update an IPv4 record.
Let use
set the default for usev4
and usev6
Rather than three separate IP discovery mechanisms (use
, usev4
,
and usev6
), have just two (usev4
and usev6
) and let the old
use
setting control the default for usev4
and usev6
:
- If neither
usev4
norusev6
is set, thenuse=foo
is equivalent tousev4=foov4,usev6=foov6
. - If
usev4
is set but notusev6
, thenuse=foo
is equivalent tousev6=foov6
. - If
usev6
is set but notusev4
, thenuse=foo
is equivalent tousev4=foov4
. - If both
usev4
andusev6
are set, thenuse=foo
is ignored.
Why this was rejected: The new design would cause existing configurations to trigger surprising, and possibly undesired (e.g., timeouts or update errors), new behavior:
- Configurations that previously updated only an IPv4 record would also update an IPv6 record.
- Similarly, configurations that previously updated only an IPv6 record would also update an IPv4 record.
Replace uses of 'wantip'
with 'wantipv4'
Rather than support 'wantip'
, 'wantipv4'
, and 'wantipv6'
, just
replace all 'wantip'
references to 'wantipv4'
.
Why this was rejected: This would break compatibility for users that
are currently updating IPv6 addresses. (Compatibility would be
restored once the update protocol callbacks are updated to honor
'wantipv6'
.)
Single if
setting for both usev4=if
and usev6=if
The proposed design calls for separate ifv4
and ifv6
settings. If
the user sets usev4=if,usev6=if
, then the user most likely wants to
use the same interface for both IPv4 and IPv6. Rather than create
separate ifv4
and ifv6
settings, have a single if
setting used
for both usev4
and usev6
.
Why this was rejected:
- Separate
v4
andv6
settings adds consistency to the configuration. - There are cases where a user will want to use a different interface. In particular, an IPv6 over IPv4 tunnel (e.g., https://tunnelbroker.net) involves creating a separate interface that is used only for IPv6.
Separate IPv4 and IPv6 credentials
In order to support providers that use separate credentials for IPv4 and IPv6 updates, the proposed design allows the user to define the same host twice. We could instead add additional options so that the user can provide both sets of credentials in a single host definition.
Why this was rejected:
-
The proposed design is easier to implement, as it does not require any modifications to existing protocol implementations.
-
The proposed design is less likely to cause problems for users that rely on globals instead of host-specific options. For example, a configuration file like the following might not do what the user expects:
ssl=true, use=if, if=eth0 protocol=foo login=username-for-ipv4 password=password-for-ipv4 loginv6=username-for-ipv6 passwordv6=password-for-ipv6 myhost.example.com protocol=bar login=username password=password # This host definition will use loginv6, passwordv6 from above # because the user didn't end each setting with a line # continuation: my-other-host.example.com
-
The proposed design provides some bonus functionality:
- Users can smoothly transition between different providers by updating both providers simultaneously until the domain registration switches to the new registrar.
- Users can take advantage of providers that support multiple A or multiple AAAA records for the same hostname, assuming each record has independent credentials.