mirror of
https://github.com/qdm12/ddns-updater.git
synced 2026-08-02 18:48:49 -04:00
Bug: Noip IPv6 update also updates IPv4 #366
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @incaseoftrouble on GitHub (Feb 5, 2024).
TLDR: An update to noip with
"ip_version": "ipv6"also modifies the IPv4In summary: I'm now using ddns-updater for my IPv6 address, however unfortunately the updates also modify the A record. I don't know if this happens from noip side or this client. If it is the former, it would be nice to be able to specify an optional, fixed IPv4 IP. If it is the latter, it would probably be nice to have
ip_version: "ipv4"/ip_version: "ipv6"mean exclusively update these and addip_version: "ipv4 and ipv6"the current behavior (or, to maintain compatibility,ip_version: "ipv6_only"?).Why this is useful: I have a dual stack connection, meaning that I get a public IPv6 but not a proper public IPv4. I solved this by pointing IPv4 traffic to an AWS instance, which, of course, has a different IP, and then proxy the traffic to the appropriate service. Updating the noip address to my "fake" public IPv4 breaks this.
For me, the issue is not urgent since my IPv6 doesn't change too often + I currently rarely need IPv4 connection.
EDIT: I think the current behavior for
ip_version: "ipv6"also isn't exactly "update both" since the current IPv4 is not checked for updating, only when an update is triggered because the IPv6 differs, then the IPv4 is also changed.@qdm12 commented on GitHub (Feb 8, 2024):
Are you using
provider_ipastrue? Because that one perhaps updates both ipv4 and ipv6 🤔 I'm thinking of removing it entirely for all providers too, so maybe something I can prioritize.@incaseoftrouble commented on GitHub (Feb 8, 2024):
Oops, forgot to include my config. No, it is false!
@qdm12 commented on GitHub (Feb 8, 2024):
What do you get in the logs when using
LOG_LEVEL=debug? It should log the url queried etc we're looking for the ones withhttps://dynupdate.no-ip.com/nic/update.@incaseoftrouble commented on GitHub (Feb 8, 2024):
Editing out some info:
It seems that no-ip tries to be clever and just updates the IPv4 if you don't provide one. In particular the IPv4 I get in the response body is my current IPv4, not the one I configured.
(TBH I have no idea how they even get the IPv4? Maybe the ddns updater is connecting to
dynupdate.no-ip.comvia IPv4?)@incaseoftrouble commented on GitHub (Feb 8, 2024):
Aha.
dynupdate.no-ip.comdoes not have an AAAA record. I think there should be something likeip1.dynupdate6.no-ip.comto connect via ipv6. Probably one should use that one if ip_version is ipv6? That would exclude the case where you are in an IPv4 only network but want to update an IPv6 address. Which might actually happen if the container is running within an IPv4 docker network, but then you can't even get IPv6 addresses I guess.@qdm12 commented on GitHub (Feb 9, 2024):
On the Noip webpage they only mention
dynupdate.no-ip.comin https://www.noip.com/support/knowledgebase/how-to-configure-ddns-in-routerApparently, noip uses the same dyndns2 protocol as described in https://help.dyn.com/remote-access-api/perform-update/
That page precises the
myipparameter works for both ivp4 and ipv6, however ddns-updater's code for now uses the query parametermyipfor IPv4 addresses, andmyipv6for iPv6 addresses, not too sure why. I think that's likely the problem: noip is not aware of themyipv6parameter and so it thinks no specific ip address was sent (sincemyipis not there), and thus uses your IPv4 address detected. This is changed to usemyip=for all IP versions in commitcb3075ea32(latest image).Actually, one more thing, I think that the provider ip parameter is a rather big problem if your public ip address is an IPv6 address (detected if version is
ipv4 or ipv6oripv6), because it will likely set an ipv4 address detected by their server, and not an IPv6 address, despite DDNS updater wanting to update with an IPv6 address 🤔 Thoughts?@incaseoftrouble commented on GitHub (Feb 9, 2024):
I think they are aware, in the sense that the IPv6 updates do work, and they do not infer the IPv6 from the connection (for two reasons: a) they can't, because the connection is IPv4 and b) updating records to an IPv6 that is not the one of the device does also work, using
ipv6_prefix). I think given that themyipis missing they automatically infer the IPv4 from the connection. (Which is maybe what you meant? I.e. the part of their code that looks atmyipdoes not see thatmyipv6is there and then infers the address from the connection, so that part thinks it has to infer the IP)I agree with always using
myipif that works for IPv6, too. (I will try out the image later)Yes and no. It depends how you connect to the provider. If you can connect to them with ipv6, they could infer your ipv6 and vice versa. But you could connect with ipv4 to update an ipv6 address etc. I think there is a way to make it work, but that just adds so much (probably unnecessary) complexity.
I think that it is fair to require that any update entry in config.json is EITHER v4 or v6, since their behavior and mechanisms are so distinct. That would also make your life easier and the behavior clearer, automatically inferring whether the updater should use ipv4 or ipv6 could lead to weird things if, e.g., the updater is on a machine with multiple network connections.
I don't actually know how fixed the priorities are? Or is IPv6 always preferred? I guess the logic could be to first try to bind a IPv6 connection and, if that doesn't work, pick an IPv4. But what if that changes? Is it an error?
I think I would be happy if
ip_versionisn't set, the updater once infers whether IPv4 or IPv6 is appropriate and then writes that to the configuration, reporting an error if later on ipv6 isn't possible.Sorry for the somewhat unsorted thoughts, just putting out there what I am thinking :)
@qdm12 commented on GitHub (Feb 9, 2024):
Indeed, the reason for the
ipv4 or ipv6is due to the public ip services not specific to an ip version. Seecb3075ea32/pkg/publicip/http/providers.go (L68-L99)For examplehttps://api.ipify.orgis for IPv4 only,https://api6.ipify.orgis for IPv6 only andhttps://api64.ipify.orgis for one or the other. There are a few others not specific to an IP version, for examplehttps://domains.google.com/checkip. Maybe it would be worth it to remove them and remove the ipv4 or ipv6 option, anyway it seems rather unused by users since it's rather confusing. But that would break some compatibility here and there, I created https://github.com/qdm12/ddns-updater/issues/642 to track changes to be made for a v3 version.Not really, it depends on the ip echo service, which is a bit... unknown I guess. For dual stack, one should really not use
ipv4 or ipv6. Ifip_versionisn't set it defaults toipv4 or ipv6and let the ip echo service send whatever IP version they prefer.Feel free to shoot more unsorted thoughts 😄
@incaseoftrouble commented on GitHub (Feb 9, 2024):
As I understand it, that in turn simply depends on what address type the client connection uses. I'm not an expert in networking etc. but AFAIK one can (optionally) fix which address type should be used when creating a socket / connection, and otherwise the system chooses.
So if you (just) write
curl https://api64.ipify.orgthen (I think) the OS determines (among others) which IP type to use (I think this is where the magic happens on Linux). I'm guessing that most systems try IPv6 first -- after all, its supposed to replace IPv4 ... eventually :D --, at least if the host name has both AAAA and A records. Then, the echo service simply sees an incoming IPv6 connection and responds with the source address.What I want to say is that the echo service really has no choice, they only see either or. Instead, if the
ddns-updaterdoes not specify which address type to use, then the OS determines what will happen. Here,ip_versioncould be used to fix the address type (in GAI-terms, specify AF_INET or AF_INET6, I don't know how to do that in Go but according to StackOverflow one should be able to specify "tcp6" or "tcp4" somewhere).@incaseoftrouble commented on GitHub (Feb 9, 2024):
Just to confirm: The change seems to work. The response body of noip now also only indicates the new ipv6.
Also, for reference, this discussion seems to be related to #507.
What could be possible to merge these ideas to not have an
ip_versionfield but maybe two fields"ipv6": { prefix, ... }and"ipv4": { ... }or similar, and only update those address families that have been specified.In case both are specified, there definitely need to be two separate calls to determine the public addresses, and then potentially one or two updates to the provider, depending on what is supported.
I guess a good idea would be something like 1) check which address families are required by any configuration entry 2) query those 3) group "necessary" updates by provider and then let provider-specific logic run all the updates?
@qdm12 commented on GitHub (Feb 9, 2024):
I would rather keep it to
ip_versionand have the optionsipv4andipv6and that's it. The program can then merge configs together for ipv4+ipv6. But for a v3 breaking change release, perhaps 🤔That's already done 😉 (once for ipv4 if any record is to be updated for ipv4, and once for ipv6 if any record is to be updated for ipv6). We just need to do #644 and also to, ideally, remove
ipv4 or ipv6.Indeed, some providers require (desec.io) to update both v4 and v6 at the same time, this should be done soon-ish with issue #507 but most providers only support a single ip, so it's a bit of a tough design to figure out 😄