"Could not resolve host" for IPv6-only names with curl in 1.18.0
Brad House
brad at brad-house.com
Wed Oct 27 00:19:33 CEST 2021
Found it, looks like ai_addrlen is being set to sizeof() the wrong
structure ... ugh.
https://github.com/c-ares/c-ares/commit/71adb3c4170dc47f71c21bf8d95ed7ddd640819e
looks like we need a quick 1.18.1...
On 10/26/21 5:35 PM, Brad House wrote:
> Erm, this is really strange. I mean just using the c-ares ahost()
> which calls ares_gethostbyname(), I get reasonable results:
>
> $ ./ahost -t u production-all-ipv6.easypost.com
> production-all-ipv6.easypost.com 2607:f0d0:2901:7e::2
> production-all-ipv6.easypost.com 2607:f0d0:3803:ca::2
> production-all-ipv6.easypost.com 2607:f0d0:2901:7e::3
> production-all-ipv6.easypost.com 2607:f0d0:3803:ca::3
>
> Using ahost instead of adig is more representative of how consumers of
> c-ares use it as adig uses low level apis whereas ahost uses the
> higher level apis.
>
> The socket(), connect(), getsockname() pattern you see for each IP
> address is actually a weird thing about getaddrinfo() where you have
> to determine reach-ability by the routes to the destination as per
> rfc6724 section 6. If you notice, the socket() is SOCK_DGRAM,
> IPPROTO_UDP and UDP is stateless, so connect() doesn't actually
> connect, but it *does* resolve if the system thinks the endpoint is
> reachable.
>
> I guess maybe I need to look at the curl code to see how its calling
> into c-ares to see if the change has some weird sanity check that
> isn't covered by our test cases.
>
>
>
> On 10/26/21 5:16 PM, James Brown via c-ares wrote:
>> Testing an upgrade from 1.17.2 to 1.18.0 and all curl requests to
>> internal names started failing with "Could not resolve host". adig
>> and ahost are both able to resolve the names just fine. It appears
>> that this affects any lookup that only returns IPv6 addresses, and
>> possibly also any lookup that is behind a DNAME. The IPv6 case is
>> easier to reproduce so that's what I've put below:
>>
>> This can be easily reproduced from `curl -vs
>> https://production-all-ipv6.easypost.com/health/ok` on any host with
>> c-ares 1.18.0 installed and curl linked against c-ares.
>>
>> Bizarrely enough, if I strace curl, I see it actually connecting to
>> the correct remote IP before returning the "Could not resolve host"
>> error. ???
>>
>> I did a git-bisect run and it points at
>> 778d7cd9e7bf6b31ce697f47cbe935e33a63a5b4
>> <https://github.com/c-ares/c-ares/commit/778d7cd9e7bf6b31ce697f47cbe935e33a63a5b4> as
>> the offending commit.
>>
>> I'm running dnsmasq on localhost and nothing about it has changed.
>> Below is some probably-relevant output from a system with c-ares
>> 1.17.2 installed system wide and c-ares 1.18.0 installed in the
>> "./prefix" directory.
>>
>> $ curl --version
>> curl 7.79.1 (x86_64-redhat-linux-gnu) libcurl/7.79.1 OpenSSL/1.0.2u
>> zlib/1.2.3 zstd/1.4.9 c-ares/1.17.2 libidn2/2.3.0 libssh2/1.10.0
>> nghttp2/1.45.1 OpenLDAP/2.4.40
>> Release-Date: 2021-09-22
>> Protocols: dict file ftp ftps gopher gophers http https imap imaps
>> ldap ldaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
>> Features: alt-svc AsynchDNS HSTS HTTP2 HTTPS-proxy IDN IPv6 Largefile
>> libz NTLM NTLM_WB SSL UnixSockets zstd
>>
>> $ env LD_LIBRARY_PATH=./prefix/lib/ curl --version
>> curl 7.79.1 (x86_64-redhat-linux-gnu) libcurl/7.79.1 OpenSSL/1.0.2u
>> zlib/1.2.3 zstd/1.4.9 c-ares/1.18.0 libidn2/2.3.0 libssh2/1.10.0
>> nghttp2/1.45.1 OpenLDAP/2.4.40
>> Release-Date: 2021-09-22
>> Protocols: dict file ftp ftps gopher gophers http https imap imaps
>> ldap ldaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
>> Features: alt-svc AsynchDNS HSTS HTTP2 HTTPS-proxy IDN IPv6 Largefile
>> libz NTLM NTLM_WB SSL UnixSockets zstd
>>
>> $ curl https://production-all-ipv6.easypost.com/health/ok
>> UP
>>
>> $ env LD_LIBRARY_PATH=./prefix/lib/ curl
>> https://production-all-ipv6.easypost.com/health/ok
>> curl: (6) Could not resolve host: production-all-ipv6.easypost.com
>> <http://production-all-ipv6.easypost.com>
>>
>> $ env LD_LIBRARY_PATH=./prefix/lib/ strace curl
>> https://production-all-ipv6.easypost.com/health/ok
>> [snip]
>> connect(5, {sa_family=AF_INET6, sin6_port=htons(53),
>> inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0,
>> sin6_scope_id=0}, 28) = 0
>> sendto(5, "Q\337\1\0\0\1\0\0\0\0\0\0\23production-all-ipv6"..., 50,
>> MSG_NOSIGNAL, NULL, 0) = 50
>> sendto(5, "~\311\1\0\0\1\0\0\0\0\0\0\23production-all-ipv6"..., 50,
>> MSG_NOSIGNAL, NULL, 0) = 50
>> poll([{fd=5, events=POLLIN|POLLRDNORM}], 1, 0) = 1 ([{fd=5,
>> revents=POLLIN|POLLRDNORM}])
>> recvfrom(5, "Q\337\201\200\0\1\0\0\0\0\0\0\23production-all-ipv6"...,
>> 4097, 0, {sa_family=AF_INET6, sin6_port=htons(53),
>> inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0,
>> sin6_scope_id=0}, [28]) = 50
>> recvfrom(5, "~\311\201\200\0\1\0\4\0\0\0\0\23production-all-ipv6"...,
>> 4097, 0, {sa_family=AF_INET6, sin6_port=htons(53),
>> inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0,
>> sin6_scope_id=0}, [28]) = 162
>> socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP) = 6
>> connect(6, {sa_family=AF_INET6, sin6_port=htons(443),
>> inet_pton(AF_INET6, "2607:f0d0:2901:7e::3", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
>> getsockname(6, {sa_family=AF_INET6, sin6_port=htons(43428),
>> inet_pton(AF_INET6, "2607:f0d0:2901:4b::66", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
>> close(6) = 0
>> socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP) = 6
>> connect(6, {sa_family=AF_INET6, sin6_port=htons(443),
>> inet_pton(AF_INET6, "2607:f0d0:3803:ca::3", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
>> getsockname(6, {sa_family=AF_INET6, sin6_port=htons(44405),
>> inet_pton(AF_INET6, "2607:f0d0:2901:4b::66", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
>> close(6) = 0
>> socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP) = 6
>> connect(6, {sa_family=AF_INET6, sin6_port=htons(443),
>> inet_pton(AF_INET6, "2607:f0d0:3803:ca::2", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
>> getsockname(6, {sa_family=AF_INET6, sin6_port=htons(33765),
>> inet_pton(AF_INET6, "2607:f0d0:2901:4b::66", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
>> close(6) = 0
>> socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP) = 6
>> connect(6, {sa_family=AF_INET6, sin6_port=htons(443),
>> inet_pton(AF_INET6, "2607:f0d0:2901:7e::2", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
>> getsockname(6, {sa_family=AF_INET6, sin6_port=htons(59083),
>> inet_pton(AF_INET6, "2607:f0d0:2901:4b::66", &sin6_addr),
>> sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
>> close(6) = 0
>> close(5) = 0
>> rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART,
>> 0x7ff5cb5f4570}, NULL, 8) = 0
>> rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART,
>> 0x7ff5cb5f4570}, NULL, 8) = 0
>> write(2, "c", 1c) = 1
>> write(2, "u", 1u) = 1
>> write(2, "r", 1r) = 1
>> write(2, "l", 1l) = 1
>> write(2, ":", 1:) = 1
>> write(2, " ", 1 ) = 1
>> write(2, "(", 1() = 1
>> write(2, "6", 16) = 1
>> write(2, ")", 1)) = 1
>> write(2, " ", 1 ) = 1
>> write(2, "C", 1C) = 1
>> write(2, "o", 1o) = 1
>> write(2, "u", 1u) = 1
>> write(2, "l", 1l) = 1
>> write(2, "d", 1d) = 1
>> write(2, " ", 1 ) = 1
>> write(2, "n", 1n) = 1
>> write(2, "o", 1o) = 1
>> write(2, "t", 1t) = 1
>> write(2, " ", 1 ) = 1
>> write(2, "r", 1r) = 1
>> write(2, "e", 1e) = 1
>> write(2, "s", 1s) = 1
>> write(2, "o", 1o) = 1
>> write(2, "l", 1l) = 1
>> write(2, "v", 1v) = 1
>> write(2, "e", 1e) = 1
>> write(2, " ", 1 ) = 1
>> write(2, "h", 1h) = 1
>> write(2, "o", 1o) = 1
>> write(2, "s", 1s) = 1
>> write(2, "t", 1t) = 1
>> write(2, ":", 1:) = 1
>> --
>> James Brown
>> Engineer
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.haxx.se/pipermail/c-ares/attachments/20211026/28e5b327/attachment.htm>
More information about the c-ares
mailing list