billfeller.github.io
billfeller.github.io copied to clipboard
curl 7.19.7 connect to ipv6 failed: Network is unreachable
Principle
i call it "IPv6 First, IPv4 Graceful degradation"
Background
the local curl version is:
$ curl -V
curl 7.19.7
when i use curl 7.19.7 to get the document that tha host is binded both ipv6 and ipv4, i just got the error incidentally below:
$ curl "http://www.desidime.com/"
curl: (7) Failed to connect to 2400:8901:1::8ba2:1a0a: Network is unreachable
remark: you can also find the dns config use Google Apps toolbox just below:
Questions
there are two questions here:
- why curl: (7) Failed to connect to 2400:8901:1::8ba2:1a0a: Network is unreachable?
- why it happened when bind both IPv6 and IPv4 accidently?
i will answer it one by one.
First, why curl: (7) Failed to connect to 2400:8901:1::8ba2:1a0a: Network is unreachable?
you know that it is not a problem with resolving IPv6 addresses. That name resolution is working fine because curl reports that it cannot reach network 2400:8901:1::8ba2:1a0a; this shows that the name translation did succeed. also you can find it in the strace log below:
$ strace -o /tmp/curl.7.19.7.log curl -6 "http://www.desidime.com/"
curl: (7) Failed to connect to 2400:8901:1::8ba2:1a0a: Network is unreachable
$ grep -n -E -A5 "connect|AF_INET" /tmp/curl.7.19.7.log
so the reason is that in order to reach an IPv6 address, you need to have a route to the destination address and very few connections have any IPv6 connectivity at all. On the machine I'm writing this, I have almost no IPv6 routes at all:
$ route -n -A inet6
Kernel IPv6 routing table
Destination Next Hop Flags Metric Ref Use Iface
fe80::/64 :: U 256 0 0 eth1
ff00::/8 :: U 256 0 0 eth1
which you can compare with IPv4 routes below:
$ route -n -A inet
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.27.12.128 0.0.0.0 255.255.255.128 U 0 0 0 eth1
169.254.0.0 0.0.0.0 255.255.0.0 U 1003 0 0 eth1
192.168.0.0 172.27.12.129 255.255.0.0 UG 0 0 0 eth1
172.16.0.0 172.27.12.129 255.240.0.0 UG 0 0 0 eth1
100.64.0.0 172.27.12.129 255.192.0.0 UG 0 0 0 eth1
10.0.0.0 172.27.12.129 255.0.0.0 UG 0 0 0 eth1
0.0.0.0 0.0.0.0 0.0.0.0 U 0 0 0 tunnat
so it means you do need an IPv6 route to the destination network and too few places provide that facility yet.
second, why it happened accidently when bind both IPv6 and IPv4?
check the different iocalls in the fail and suc log, i found that when it failed, it directly connect to IPv6 and not connect to IPv4. and in our network IPv6 is not rounted as above. so i think it may be the network misconfiguration or maybe wrong dns cache lead to.
Solutions
now we need to give the solutions to solve it.
-
you can ops Ipv6 network architecture to support ipv6 network.
-
you can just resolve name to IPv4 address by the option -4 as below
$ curl -h|grep 'Resolve name to IPv' -4/--ipv4 Resolve name to IPv4 address -6/--ipv6 Resolve name to IPv6 address $ curl -4 -I "http://www.desidime.com" HTTP/1.1 200 OK
More Infomation About IPv6 and IPv4
ref from How does a device know when to use IPv4 or IPv6?
When a client wants to connect to a server (e.g., www.desidime.com), the client issues two DNS requests in parallel: one request for IPv4 addresses, and one request for IPv6 addresses. After receiving the responses, the client generally follows the process described in IETF standard RFC3484 ”Default Address Selection for IPv6” which leans towards an assumption that dual stack is a state of transitioning towards and IPv6-only network, and hence prefers IPv6 above IPv4 by design. When a client receives a response including both an IPv4 and IPv6 address then based upon RFC3484 the IPv6 address is the preferred address. If, for whatever reason, the usage of that address was non-successful, an alternate address will be used, potentially a valid IPv4 address to connect to the remote location.
rfc3484 10.3. Configuring Preference for IPv6 or IPv4
10.3. Configuring Preference for IPv6 or IPv4
The default policy table gives IPv6 addresses higher precedence than IPv4 addresses. This means that applications will use IPv6 in preference to IPv4 when the two are equally suitable.
in the figure below that curl 7.50.1 has implement new strategy called Happy Eyeballs: Success with Dual-Stack Hosts to open up a connection over BOTH IPv4 and IPv6 and use whichever one is fastest. so it can also solve the problem perfectly. It is up to the client to decide which address it will use to connect to the remote Internet resource more reliable, not just the preferred IPv6 in rfc3484.txt.
```bash
$ strace -o /tmp/curl.7.50.1.log /tmp/****/curl/bin/curl "http://www.desidime.com"
$ cat /tmp/curl.7.50.1.log |grep -n -P -A5 "connect|AF_INET"
```

Reference
hi, how to curl php with proxy ipv6 ? thank