30

I just upgraded from Mavericks to Yosemite, and now curl can't see loopback host names.

Set up a simple http server to test:

$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

Now I can hit localhost:8000 in chrome. I can even wget it. But in curl, this happens:

$ curl localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused

However, this works:

$ curl 127.0.0.1:8000

I read this answer about wget proxy settings, but it didn't help, because this works:

$ wget --proxy=off localhost:8000

This is really frustrating, because I have a few different loopback hostnames listed in my /etc/hosts file so I can develop apps locally, and I'm used to debugging them with curl.

I've tried with the version of curl that ships with osx:

$ curl --version
curl 7.37.1 (x86_64-apple-darwin14.0) libcurl/7.37.1 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IPv6 Largefile NTLM NTLM_WB SSL libz

$ curl localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused

$ curl 127.0.0.1 # works

And I've tried compiling curl with brew:

$ /usr/local/Cellar/curl/7.38.0/bin/curl --version
curl 7.38.0 (x86_64-apple-darwin14.0.0) libcurl/7.38.0 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: IPv6 Largefile NTLM NTLM_WB SSL libz

$ /usr/local/Cellar/curl/7.38.0/bin/curl localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused

$ /usr/local/Cellar/curl/7.38.0/bin/curl 127.0.0.1:8000 # works
2
  • I ran into a similar problem testing a node.js application. I saw that node's debugging said it was binding to 0.0.0.0, and tried 'curl -4 localhost...' and it worked, but without the -4 it failed. It appears the IPv6 address is being resolved out of /etc/hosts before the IPv4 one.
    – Neth
    Nov 20, 2014 at 20:30
  • I'm having the same issue you've described Nick.
    – nerdburn
    Nov 21, 2014 at 22:23

3 Answers 3

36

I just got it to work by commenting out one of the IPv6 loopback lines from my /etc/hosts file:

#fe80::1%lo0    localhost

Now all of my loopback hostnames work, not just localhost. I wonder what's up with this?

2
  • I had that and it helped me as well. I don't know what's the deal with that line; it seeems my system had it from before Yosemite.
    – mislav
    Nov 4, 2014 at 21:43
  • Thank you so much. I wonder though, why at the core it favors the IPv6 for the loopback device over the IPv4. This only started happening for me on Yosemite. Jan 21, 2015 at 17:01
24

Alternative (does not require sudo or modifying /etc/hosts) - always use ipv4 until curl gets smarter.

$ echo '--ipv4' >> ~/.curlrc

(then everything will work as desired)

1
  • Thanks — this problem was driving me nuts, but your solution worked perfectly.
    – Kyle Fox
    Jul 16, 2015 at 4:36
2

First of all, 0.0.0.0 is a special address meaning "any IPv4 address".

A socket can be bound to either IPv4 or IPv6 protocol. If a socket is bound to 0.0.0.0, that means it will listen to any IPv4 trying to connect to it, and will be represented as it follows:

$ nc -l 0.0.0.0 8085
$ lsof -i4 -Pnl | grep 8085
  nc        23994 [xxx]    3u  IPv4 [xxx]      0t0  TCP *:8085 (LISTEN)

The * sign is equivalent to 0.0.0.0 on IPv4.

For IPv6:

$ nc -l :: 8085
$ lsof -i6 -Pnl | grep 8085
  nc        24145 [xxx]    3u  IPv6 [xxx]      0t0  TCP *:8085 (LISTEN)

The * sign is equivalent to :: on IPv6, as in the official specification.

The reason is that curl tries to resolve to a random localhost entry in /etc/hosts, and as @NickRetallack mentioned, that entry is the chosen one by curl when resolving localhost in its default mode (assumedly IPv6 or IPv4, whatever resolves first).

Forcing it in --ipv4 mode, as @CharlesHebdough suggested, will make curl resolve localhost to 127.0.0.1 (assuming there are no other IPv4 entries for localhost in /etc/hosts).

Each implementation will resolve localhost as they wish, hence why you had intermittent success with different tools.

To be the most precise possible, use 127.0.0.1 instead of localhost, but it will bound you to IPv4. localhost gives you the flexibility to work in both IPv6 and IPv4 protocols, however in some implementations you might have trouble, as in that specific version of curl.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.