desec-stack
desec-stack copied to clipboard
Ipv6 change request overrides ipv4 and vise versa
My openwrt is configured to use desec as dyndns like this:
So there are two processes that update ipv4 and ipv6 separately making requests:
https://update.dedyn.io/?username=&password=&hostname=myhost&myipv4=127.0.0.1
https://update.dedyn.io/?username=&password=&hostname=myhost&myipv6=::1
And it seems like request to update ipv6 wipes ipv4 and request to update ipv4 wipes ipv6.
This works as documented. If you want to keep the other IP address, you can provide it explicitly in another query string parameter (i.e. you can provide both myipv4
and myipv6
). (IP addresses are also inferred from the connection type, so if you make an IPv4 connection, you can skip the IPv4 parameter; the same is true for IPv6.)
The rationale for this behavior is that we think that it breaks in less scenarios. For example, when someone has Internet access that supports IPv4 and IPv6, they can make an update request via an IPv6 connection and additionally provide the IPv4 address in the URL, and both will be set (the IPv6 address will be inferred from the connection). If the user now switches to an IPv4-only connection, future updates will be made via IPv4, and no IPv6 will be found. It will thus be deleted.
If the system did not behave like that, it is very likely that the user will forget to specify an empty myipv6=
parameter to delete the old address. As a result, the old IPv6 address would remain in the DNS, the user very likely being unaware of it. This would cause timeouts and potentially a vulnerability. The policy is thus that if you want to set both IPv4 and IPv6 addresses, they have to be part of the same update request.
We can of course change this if there are compelling arguments why a different behavior would be superior (but it would be quite difficult not to break existing installations). Do you have additional arguments why the current behavior is incorrect?
Your original comment stated the observation, but gave no arguments. I am thus closing the issue (but can reopen when new arguments are expressed).
Thanks @peterthomassen , I will not reopen the issues as I was looking to figure if it was intended behaviour. However I can see a few reasons pro empty parameter:
- Empty parameter is less ambiguous than IP inferring from request
- Presence of parameters in the request indicate that either user or vendor is in control of parameters and can add/remove params to control intended behaviour
- URL semantics suggests it is 'update' rather than 'set'/'override' endpoint
I can see two possible scenarios:
Device can send simple non-configurable update request: This is where I'd expect server to infer my IP from the connection.
Device can be configured to send proper request:
This is where I'd expect server to accept user supplied params. I.e. If I specify myipv6=remove
or myipv6=
or myipv6=::
(myipv4=0.0.0.0
) I'd expect server to remove that record, and keep it otherwise.
I would also expect IP inferring from connection and parameters to be mutually exclusive, rationale: if your user can specify where to put ipv4 param, the user also should be capable to do so for ipv6
Alternatively, consider myipv6=preserve
option.
Thoughts regarding IP inferring: IP inferring has much more sense for ipv4 because the device can be behind several NATs and thus have issues identifying real IP. Contrary for ipv6 - if the interface doesn't have global ipv6 then no ipv6 ,and if it has - that's the real IP. So it has much more sense to infer ipv4 and supply ipv6, but yes, ipv6 will most probably be used by default to establish connection.
Since in most cases ipv6 should be preferred connection I would probably implement something like this:
- make an endpoint with ipv6+ipv4 address e.g.
update6.dedyn.io/update-me
, at this endpoint I'd either infer ipv6 and redirect(302) to ipv4 only endpoint e.g.update4/update-me
or infer ipv4 if request comes from ipv4 address - infer ipv4 when it comes to
update4/update-me
Thank you for your interesting thoughts! Given the specific ideas you have (several of which I support), would you like to contribute these features? (If yes, let's agree on the interface before you start spending time on code.)
For reference, you can find the code that implements the current behavior here: https://github.com/desec-io/desec-stack/blob/master/api/desecapi/views.py#L343-L380
Related to #13.
@peterthomassen , I would love to contribute, but given I have too many side-project at this time I'm afraid I won't produce good enough code. I'll try to find time later, though!
We only support this quirky interface because it so many routers support it out-of-the-box. In your case, you seem to have far-reaching control over which software your router is running. Why not use the REST API in this case? It has much better behavior and allows for fine-grained control over how you want to update the DNS information.
Anyways, I think the ipv6=preserve
(and ipv4=preserve
) option could be a valuable extension of the quirky update API that we are currently providing.