Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer IPv6 over IPv4 #1469

Closed
FliesLikeABrick opened this issue Jan 7, 2025 · 22 comments · Fixed by #1470
Closed

Prefer IPv6 over IPv4 #1469

FliesLikeABrick opened this issue Jan 7, 2025 · 22 comments · Fixed by #1470
Assignees
Labels
dns enhancement New feature or request tui
Milestone

Comments

@FliesLikeABrick
Copy link

Describe the feature you'd like
We would like trippy to implement a more typical AF/source address selection policy. Currently the default is "IPv4 then IPv6", however this is the opposite of every other typical system and application default behavior. This leads to users or administrators who use trippy capturing data that does not show the same path/transport their application or system is using, leading to confusing diagnostics and communication.

Change the default AF/source address selection from Ipv4thenIpv6 to ipv6-then-ipv4

Describe alternatives you've considered

Additional context

@fujiapple852
Copy link
Owner

fujiapple852 commented Jan 8, 2025

@FliesLikeABrick see #864 for a previous discussion on this topic.

this is the opposite of every other typical system and application default behavior

Can you give some examples? On my system (macOS) both ping and traceroute default to IPv4, whereas ping6 and traceroute6 default to IPv6.

I also tried curl:

$ curl http://google.com -v
* Host google.com:80 was resolved.
* IPv6: 2a00:1450:4009:81d::200e
* IPv4: 142.250.187.238
*   Trying 142.250.187.238:80...
*   Trying [2a00:1450:4009:81d::200e]:80...
* Connected to google.com (142.250.187.238) port 80

I have to add -6 to curl to force it to use IPv6. Edit: see this recent discussion on changing curl to prefer IPv6.

This leads to users or administrators who use trippy capturing data that does not show the same path/transport their application or system is using, leading to confusing diagnostics and communication

In practice, why is this an issue given the default can be changed to ipv6-then-ipv4 via cmd line flags or permanently via the config file?

@fujiapple852
Copy link
Owner

fujiapple852 commented Jan 8, 2025

One option here may be to support a "whatever comes back first" mode, i.e. something like --addr-family first-to-respond.

For the default system resolver, which ultimately calls getaddrinfo with a default value for address (i.e. no protocol family preference), this mode would return the first resolved address, which should respect the local OS rules, i.e. gai.conf on Linux.

The other resolvers (namely google, cloudflare & resolv) use the hickory-dns client which supports a Ipv4AndIpv6 mode which queries both in parallel (a deliberate race).

One issue that occurs to me is that, as this mode would be racy, it could lead to confusing user experience where you may get either IPv4 or IPv6 each time you run trip.

And of course, it would still be a significant breaking change to adjust the default value for --addr-family to be first-to-respond.

Edit:

WIP impl of first-to-respond here: #1470

Testing it locally, I do indeed see the "flip/flop" between IPv4/IPv6 issue mentioned above.

Edit 2:

The name first-to-respond is accurate for the google, cloudflare & resolv resolvers, as the IPv4/IPv6 lookups genuinely happen in parallel and it is a race as to which one is returned first. For the default system resolver however it may not be accurate, it depends on the behaviour and configuration of getaddrinfo on the OS.

Therefore, a better name may be something like "any" or "unspecified" or "ipv4-or-ipv6" as we are telling Trippy "I don't care if I get IPv4 or IPv6, just return the first addr the OS gives us or the first thing that works if we're not using the OS DNS resolver".

PR updated to be either.

Edit 3:

Another issue with this approach I just experienced is that, if your system DNS resolver support both IPv4 and IPv6, but you do not have IPv6 connectivity, you will get BSOD errors when IPv6 is chosen but there is no IPv6 routing. For example, on my system with IPv6 routing disabled I get:

IO error: Connect error for [2404:6800:4005:819::200e]:80: No route to host (os error 65)

@c-git
Copy link
Collaborator

c-git commented Jan 8, 2025

I don't have access to IPv6 so have no personal stake but I don't think I'd like the race option in a diagnostic tool.

@FliesLikeABrick
Copy link
Author

FliesLikeABrick commented Jan 11, 2025

@fujiapple852 ping and traceroute have the appearance of preferring IPv4 first, however on MacOS and Linux (up until recently in some distros), ping6 and traceroute6 are separate utilities. mtr prefers IPv6 over IPv4, and so do the newer dual-stack versions of ping being distributed in some Linux distros (instead of the separate ping vs ping6 utilities). fping also has converged fping and fping6 into one utility or wrapper, which prefers IPv6.

Browsers and all other userland applications prefer IPv6 first when using default source address selection strategies, on all OSes. This is why trippy implementing a different default strategy is misleading for users, administrators, and others who are troubleshooting on dual-stack systems. The diagnostic tools should mirror the default system and application behaviors.

I completely agree with @c-git that non-deterministic behavior should be avoided in this tool, as it is in others.

@fujiapple852
Copy link
Owner

Background

Trippy will typically be given a IPv4 or IPv6 address as input and so no decision is required. As a convenience Trippy supports taking a hostname as input and attempts to resolve this to a IPv4 or IPv6, which is where, in the absence of any user supplied preference, a decision is required.

Trippy should, in general, be unopinionated on such matters. The correct thing to do in such cases is defer the decision to the OS and therefore avoid having a default value in Trippy.

Current Default Behaviour

The current default behaviour for Trippy is:

  • --dns-resolve-method system
  • --addr-family ipv4-then-ipv6

Proposed New Default Behaviour

The proposed new default behaviour for Trippy is:

  • --dns-resolve-method system
  • --addr-family system

This introduces a new system value for --addr-family which solves the problem for users who have not provided any explicit preference by deferring the decision to the OS.

Edge Case

It does leave one problem however, namely how to deal with the case where --dns-resolve-method is set to be google, cloudflare or resolv and --addr-family is set to the (newly proposed) default of system. This case is problematic as these do not use the OS resolver and so an explicit decision is needed as to what either means.

The options here are, for the non-system resolvers:

  • try both IPv4 and IPv6 in parallel and use whichever comes back first, non-deterministically
  • fail on startup with an invalid configuration error
  • try IPv6 then IPv4

I think we can rule out the first option, due to the non-determinism.

The second option is better but not very user friendly, as it forces you to configure both --dns-resolve-method and --addr-family at the same time. This would also break existing users who have configured a non-default resolver.

That leaves the 3rd option, where Trippy does express an opinion to favour IPv6 over IPv4, but only when the user has opted into using a non-default resolver. This is a breaking change but seems acceptable.

Note on System tools vs Applications

This still leaves the matter of the behaviour of Trippy differing for some other applications, such as web browsers, which are opinionated about IPv4 vs IPv6 and choose to override the OS resolver behaviour.

Unlike regular applications such as web browsers, where the choice of IP protocol is a low level detail that the user should not be aware of, for system tools such as Trippy the choice matters. For example, the UDP/dublin algorithms for IPv4 and IPv6 are very different.

Therefore I think trying to match the behaviour of application such as web browser is a non-goal for Trippy.

Rollout

I propose the following rollout timetable:

  • 0.13.0 (~Q1 2025): add a system address family and announce the intent to change the default behaviour in the next major release
  • 0.14.0 (~Q2 2025): change the default address family to be system

@FliesLikeABrick
Copy link
Author

That leaves the 3rd option, where Trippy does express an opinion to favour IPv6 over IPv4, but only when the user has opted into using a non-default resolver. This is a breaking change but seems acceptable.

I agree with this being the best of the options given

@fujiapple852
Copy link
Owner

follow up breaking change in 0.14.0 to change the default address family to system: #1475

@fujiapple852 fujiapple852 removed the breaking A breaking change label Jan 14, 2025
@c-git
Copy link
Collaborator

c-git commented Jan 14, 2025

I also think the third options is the best of the 3.

But... Is there an advantage to IPv6 over IPv4?

Why not just leave it as IPv4 then IPv6 if they leave it on system and choose an non-system resolver?

PS. But I am ok with going with the third option.

@fujiapple852
Copy link
Owner

@c-git it's a good thought; it would mean the breaking change (to use the system address family by default) becomes smaller in scope which is a good thing.

With your suggestion, it only impacts those who use the default system resolver.

Those who currently configure a non-system resolver but do not configure a address family will not be impacted as they'll continue to default to ipv4-then-ipv6.

@c-git
Copy link
Collaborator

c-git commented Jan 14, 2025

Yeah, I think it strikes a nice balance and is a "reasonable" default in as much as it will do what the system it is on does by default. I'd actually argue that IPv4 is still the default in most places in terms of most tools. Seems many tools added a new version with a 6 so the "default" with no number is still 4.

@FliesLikeABrick
Copy link
Author

FliesLikeABrick commented Jan 14, 2025

Yeah, I think it strikes a nice balance and is a "reasonable" default in as much as it will do what the system it is on does by default. I'd actually argue that IPv4 is still the default in most places in terms of most tools. Seems many tools added a new version with a 6 so the "default" with no number is still 4. edit: I think you are referring to like ping vs ping6, traceroute vs traceroute6, etc. I would say those are the vast minority, and multiple software ecosystems with those tools are beginning to converge them into a single tool or wrapper that supports both AFs, so this your statements could be misleading. There are probably fewer than 5 tools in common use that use "X" vs "X6", versus however many thousands or hundreds of thousand of applications that have dual-stack support, do not require the user to discriminate, and prefer IPv6 over IPv4 by default

I am not 100% sure what you are referring to and would love examples of tools that have v4+v6 support but default to IPv6 -- that has not been my experience

I am not sure your background or experience, but I would encourage you to educate yourself further on how IPv6 is deployed and adopted in "dual stack" environments - as this is the way that IPv6 is rolled out to all kinds of content/datacenter, commercial/enterprise, and residential environments. Approximately 50% of US users have IPv6 available for example - and those are pretty much all dual-stack (having IPv4 and IPv6). IPv6 is used by default on all hosts/systems that have both IPv4 and IPv6 available (with different timeouts or fallbacks to IPv4 based on multiple layers of considerations that may be application and OS-specific)

@c-git
Copy link
Collaborator

c-git commented Jan 15, 2025

I have very little experience with IPv6, none of my ISPs have ever offered it. The opinion was based on the default versions being the IPv4 versions and having alternate versions suffixed with a 6. I re-read the messages and based on this comment

@fujiapple852 ping and traceroute have the appearance of preferring IPv4 first, however on MacOS and Linux (up until recently in some distros), ping6 and traceroute6 are separate utilities. mtr prefers IPv6 over IPv4, and so do the newer dual-stack versions of ping being distributed in some Linux distros (instead of the separate ping vs ping6 utilities). fping also has converged fping and fping6 into one utility or wrapper, which prefers IPv6.

It does suggest a trend of moving from only IPv4 support with a separate binary for IPv6 towards changing the default as you said. If the long term trend is indeed IPv6 as the default maybe since we are already making a breaking change we should change now. However, it does mean that we break people who currently don't use the system resolver and don't need to be broken. While people who don't change the default will get the same as the system (and thus default to IPv6 in dual stack based on the above referenced comment).

@fujiapple852
Copy link
Owner

With your suggestion, it only impacts those who use the default system resolver.

Thinking about it some more, there is one scenario I did not consider; after the breaking change to make the default address family system, a user who starts off with the default configuration and then later changes to use a non-system resolver (i.e. google, cloudflare or resolv) will experience a change from ipv6-then-ipv4 (which is the most likely behaviour from the system resolver) to ipv4-then-ipv6 (our previously proposed default).

Therefore I think it is better that the system address family default to ipv6-then-ipv4 for the non-system resolvers. This does increase the scope of the breaking change in 0.14.0 as noted above, but I think it is the lesser of evils here.

@c-git
Copy link
Collaborator

c-git commented Jan 25, 2025

That is true and breaking less often is better I think. Even if it means we have to break a bit more.

@FliesLikeABrick
Copy link
Author

I have built and run this from master after the PR was merged and the default behavior still appears to use IPv4 -- @fujiapple852 did you or someone else test this branch out?

@fujiapple852
Copy link
Owner

@FliesLikeABrick to recap on the rollout plan:

0.13.0 (~Q1 2025): add a system address family and announce the intent to change the default behaviour in the next major release. This is what is on master today.

0.14.0 (~Q2 2025): change the default address family to be system. This is being tracked in #1475 and will be available on master after 0.13.0 has been released.

@FliesLikeABrick
Copy link
Author

FliesLikeABrick commented Feb 12, 2025

@fujiapple852 understood and agreed it's a solid plan -- however I ran trip -r system google.com and observed that it was still using IPv4. The default has not been switched to system yet, however we would expect -r system to use the new IPv6-preferring behavior, correct? Also thank you for the prompt reply/engagement - we would love to deploy this tool internally and are in the process of vetting it

@fujiapple852
Copy link
Owner

@FliesLikeABrick use -F system to change the address family to the new system value. This will be the default on 0.14.0, but for now has to be opted in.

Aside: the -r system option changes the resolver, which is system by default so not needed here.

@FliesLikeABrick
Copy link
Author

@fujiapple852 perfect thank you -- I see now that I was indeed confusing the resolver vs family options, both of which have system values available. Indeed -F system works as-expected, and I look forward to the default behavior change.

If we wanted to deploy this internally via a fork until 0.14 is released, I presume there's a one-line change we just need to make somewhere to change the default -- possibly line 116 in src/config.rs ?

https://github.com/fujiapple852/trippy/blob/938348c46563020e94fbe22d3ba85b5d754bade6/crates/trippy-dns/src/config.rs#L116C1-L116C53

@fujiapple852
Copy link
Owner

@FliesLikeABrick I’m not near a laptop to check, however I believe this is where you would want to change the default:

pub const DEFAULT_ADDR_FAMILY: AddressFamilyConfig = AddressFamilyConfig::Ipv4ThenIpv6;

@FliesLikeABrick
Copy link
Author

Thanks @fujiapple852 confirmed changing that line to instead use AddressFamilyConfig::System changed the default behavior for us to deploy internally until 0.14.0 is released. Thanks everyone for the quick and productive engagement on this suggestion

@c-git
Copy link
Collaborator

c-git commented Feb 13, 2025

And thank you for raising this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dns enhancement New feature or request tui
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants