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

curl with c-ares tries to resolve an URL with ipv6 w/ zone index when passed in as a proxy #3482

Closed
yukwunhang opened this issue Jan 17, 2019 · 3 comments

Comments

@yukwunhang
Copy link

yukwunhang commented Jan 17, 2019

I did this

curl tries to resolve an IPv6 address w/ zone index as if it's a hostname when

  • curl is built with c-ares
  • an URL with an IPv6 address with zone index
  • URL is set as the proxy
[root@localhost bin]# ./curl -V
curl 7.63.0-DEV (x86_64-unknown-linux-gnu) libcurl/7.63.0-DEV c-ares/1.14.0
Release-Date: [unreleased]
Protocols: dict file ftp gopher http imap pop3 rtsp smtp telnet tftp
Features: AsynchDNS IPv6 Largefile UnixSockets

[root@localhost bin]# ./curl -v -x http://[fe80::e23f:49ff:fe7e:465d%enp0s25]:80 http://example.com
* Please URL encode % as %25, see RFC 6874.
* Could not resolve: fe80::e23f:49ff:fe7e:465d%enp0s25 (Domain name not found)
* Closing connection 0
curl: (5) Could not resolve: fe80::e23f:49ff:fe7e:465d%enp0s25 (Domain name not found)

Doesn't work if % is encoded as %25 either:

[root@localhost bin]# ./curl -v -x http://[fe80::e23f:49ff:fe7e:465d%25enp0s25]:80 http://example.com
* Could not resolve: fe80::e23f:49ff:fe7e:465d%25enp0s25 (Domain name not found)
* Closing connection 0
curl: (5) Could not resolve: fe80::e23f:49ff:fe7e:465d%25enp0s25 (Domain name not found)

Bug is also reproducible with a program written against libcurl and setting CURLOPT_PROXY to [fe80::e23f:49ff:fe7e:465d%enp0s25]

I expected the following

curl w/o c-ares works, but only if % is not encoded as %25 (as recommended)

[root@localhost bin]# ./curl -V
curl 7.63.0-DEV (x86_64-unknown-linux-gnu) libcurl/7.63.0-DEV
Release-Date: [unreleased]
Protocols: dict file ftp gopher http imap pop3 rtsp smtp telnet tftp
Features: AsynchDNS IPv6 Largefile UnixSockets

[root@localhost bin]# ./curl -v -x http://[fe80::e23f:49ff:fe7e:465d%enp0s25]:80 http://example.com
* Please URL encode % as %25, see RFC 6874.
*   Trying fe80::e23f:49ff:fe7e:465d...
* TCP_NODELAY set
* Connected to fe80::e23f:49ff:fe7e:465d%enp0s25 (fe80::e23f:49ff:fe7e:465d) port 80 (#0)
> GET http://example.com/ HTTP/1.1
> Host: example.com
> User-Agent: curl/7.63.0-DEV
> Accept: */*
> Proxy-Connection: Keep-Alive
>
* HTTP 1.0, assume close after body
< HTTP/1.0 404 File not found
< Server: SimpleHTTP/0.6 Python/2.7.5
< Date: Wed, 16 Jan 2019 17:59:14 GMT
< Content-Type: text/html
< Connection: close
<
<head>
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code 404.
<p>Message: File not found.
<p>Error code explanation: 404 = Nothing matches the given URI.
</body>
* Closing connection 0

(The server is actually a simple HTTP server and not a proxy, but is enough to illustrate this bug.)

if encoded as %25:

[root@localhost bin]# ./curl -v -x http://[fe80::e23f:49ff:fe7e:465d%25enp0s25]:80 http://example.com
* Could not resolve proxy: fe80::e23f:49ff:fe7e:465d%25enp0s25
* Closing connection 0
curl: (5) Could not resolve proxy: fe80::e23f:49ff:fe7e:465d%25enp0s25

curl/libcurl version

tested:

  • curl 7.64.0 (master), 7.63.0, 7.62.0, 7.61.0, 7.59.0
  • c-ares 1.14.0, 1.15.0

operating system

[root@localhost bin]# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
@bagder
Copy link
Member

bagder commented Jan 21, 2019

This issue actually seems independent of resolver backend. The code basically never handles or strips off the zone string before it gets sent to the resolver function. The string will then not be treated an IPv6-only address and gets passed to the actual name resolver function, which in the c-ares case will fail like above but I'm pretty sure it might also fail.

In the report it mentions how '%' only works but not '%25', which is probably because the string isn't properly URL decoded before passed on to the resolver function and the reporter's resolver function seems to deal with the zone index. In my tests with the threaded resolver, this setup triggered errors similar to the c-ares case. (Possibly because of the wrong zone/IP.)

@yukwunhang
Copy link
Author

Thanks for looking into this! For what It's worth, a somewhat hacky workaround (on Linux at least) I've found is to parse out the zone index from the URL and specify the interface via CURLOPT_INTERFACE instead.

@bonebizz21
Copy link

Yay

bagder added a commit that referenced this issue May 21, 2019
If the proxy string is given as an IPv6 numerical address with a zone
id, make sure to use that for the connect to the proxy.

Fixes #3482
@bagder bagder closed this as completed in 12e564c May 22, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Aug 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
3 participants