Mac OS X Yosemite での Curl ローカルホスト名

Mac OS X Yosemite での Curl ローカルホスト名

Mavericks から Yosemite にアップグレードしたところ、curlループバック ホスト名が表示されなくなりました。

テスト用に簡単な http サーバーをセットアップします。

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

これで、Chrome で localhost:8000 にアクセスできるようになりました。wget も実行できます。しかし、curl では次のようになります。

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

ただし、これは機能します:

$ curl 127.0.0.1:8000

私は読むwgetプロキシ設定に関するこの回答しかし、これは役に立ちませんでした。なぜなら、これは機能するからです:

$ wget --proxy=off localhost:8000

/etc/hostsこれは本当にイライラします。なぜなら、ローカルでアプリを開発できるようにファイルにいくつかの異なるループバック ホスト名がリストされており、curl を使用してデバッグすることに慣れているからです。

OSX に同梱されている curl のバージョンを試してみました:

$ 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

そして、brew で curl をコンパイルしてみました:

$ /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

答え1

/etc/hosts ファイルから IPv6 ループバック行の 1 つをコメント アウトすることで動作するようになりました。

#fe80::1%lo0    localhost

これで、localhost だけでなく、すべてのループバック ホスト名が機能するようになりました。これは一体どういうことでしょうか?

答え2

代替(sudo や変更は必要ありません/etc/hosts)- curl がより賢くなるまで、常に ipv4 を使用します。

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

(そうすればすべてが期待通りに動作するでしょう)

答え3

まず、 は0.0.0.0「任意の IPv4 アドレス」を意味する特別なアドレスです。

ソケットは IPv4 または IPv6 プロトコルにバインドできます。ソケットが にバインドされている場合0.0.0.0、ソケットは接続しようとするすべての IPv4 をリッスンし、次のように表されます。

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

この記号はIPv4 の場合*と同等です。0.0.0.0

IPv6の場合:

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

この記号はIPv6では次の*記号と同等です。::公式仕様書にあるように

その理由は、 が内のcurlランダムなエントリを解決しようとするためであり、@NickRetallack が述べたように、そのエントリはのデフォルト モード (おそらく IPv6 または IPv4、最初に解決される方) で解決するときに によって選択されるエントリです。localhost/etc/hostscurllocalhost

@CharlesHebdough が示唆したように、これを モードで強制すると--ipv4、が にcurl解決されます (に他の IPv4 エントリがないことを前提とします)。localhost127.0.0.1localhost/etc/hosts

localhostそれぞれの実装は希望どおりに解決されるため、さまざまなツールで断続的に成功することになります。

できるだけ正確にするには、127.0.0.1localhost の代わりに を使用しますが、IPv4 にバインドされます。 をlocalhost使用すると、IPv6 プロトコルと IPv4 プロトコルの両方で作業できる柔軟性が得られますが、 の特定のバージョンのように、実装によっては問題が発生する可能性がありますcurl

関連情報