From: "kjtsanaktsidis (KJ Tsanaktsidis)" <noreply@...>
Date: 2022-12-04T02:02:48+00:00
Subject: [ruby-core:111195] [Ruby master Bug#19144] Ruby should set AI_V4MAPPED | AI_ADDRCONFIG getaddrinfo flags by default

Issue #19144 has been updated by kjtsanaktsidis (KJ Tsanaktsidis).





A gentle poke to see if anybody has some thoughts on this?



----------------------------------------

Bug #19144: Ruby should set AI_V4MAPPED | AI_ADDRCONFIG getaddrinfo flags by default

https://bugs.ruby-lang.org/issues/19144#change-100478



* Author: kjtsanaktsidis (KJ Tsanaktsidis)

* Status: Open

* Priority: Normal

* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN

----------------------------------------

Currently, DNS lookups made with `getaddrinfo` from Ruby (i.e. not from the `Resolv` module) cause both A and AAAA DNS requests to be made, even on systems that don���t actually have an IPv6 address that could possibly make the AAAA response useful. I wouldn���t _really_ care about this, normally, but glibc has a bug (https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1961697) which can cause a 5-second delay in DNS lookups when both A and AAAA records are queried in parallel. This bug is fixed in glibc upstream but still present in some LTS linux distros (Ubuntu 18.04 and 20.04 at least), so I think it���s worthwhile to try and work around it in circumstances where the AAAA request is pointless anyway.



The dual A/AAAA lookup happens because whenever Ruby calls getaddrinfo to perform DNS lookups, it always sets `hints`, and sets  `hints->ai_flags` to zero by default unless flags are specified by the caller (e.g. `AI_PASSIVE` is set when binding a TCP server socket in `TCPServer.new`).



This matches the default value of `ai_flags` specified by POSIX, which is zero. However, glibc behaves differently. When glibc���s `getaddrinfo` function is called with `NULL` for the `hints` parameter, it defaults the `ai_flags` value to `(AI_V4MAPPED | AI_ADDRCONFIG)`. The manpage (from the Linux man-pages project - https://man7.org/linux/man-pages/man3/getaddrinfo.3.html) claims ���this is an improvement on the standard��� (although I couldn���t find this mentioned in the glibc manual itself).



Of course, we���re not _actually_ ever calling `getaddrinfo` with NULL `hints`; so, we never actually use these flags on glibc systems (unless they���re explicitly specified by the caller).



My proposal is that we should change Ruby to set these two flags by default, when they���re available, in the following circumstances:

* In all calls made internally to `rsock_getaddrinfo` as a result of socket functions like `TCPSocket.new`, `UDPSocket.new`, etc.

* EXCEPT when `AI_PASSIVE` is also set (i.e. when we���re trying to get an address to bind for listener socket - see below)

* In calls made to `rsock_getaddrinfo` as a direct result of calling `Addrinfo.getaddrinfo` from Ruby with nil flags

* EXCEPT calls to `Addrinfo.getaddrinfo` where explicit flags are provided



Both of these seem like something you would almost always want to be doing in any outgoing connection scenario:

* `AI_V4MAPPED` ensures that, if AF_INET6 is explicitly specified as the desired protocol, and there is no AAAA record in DNS, that any A record that _is_ present gets converted to an IPv4-mapped IPv6 address so it can be used e.g. with NAT64.

* `AI_ADDRCONFIG` ensures that, if a machine has no IPv6 address, it doesn���t bother making an AAAA lookup that will return IPv6 addresses that can���t actually be used for anything (and vice versa for IPv4).



The reason why we wouldn���t want to set `AI_ADDRCONFIG` in circumstances where Ruby currently sets `AI_PASSIVE` is that loopback addresses are not considered in deciding if a system has an IPv4/IPv6 address. Conceivably, you might want to bind to a `::1` loopback address, and allow other processes on the same machine to connect to that.



Does changing this default sound reasonable? If so I can prepare a patch. Another option I considered is doing this _only_ when Ruby is built against glibc (so that other system behaviour is most closely matched).











-- 

https://bugs.ruby-lang.org/

 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/