web-dev-qa-db-ja.com

Mac OS X Yosemiteのローカルホスト名をカールする

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

テストする単純なhttpサーバーを設定します。

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

これで、Chromeでlocalhost:8000を打つことができます。私もそれを得ることができます。しかし、カールではこれが起こります:

$ 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でカールをコンパイルしてみました:

$ /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
30
Nick Retallack

/ etc/hostsファイルからIPv6ループバック行の1つをコメントアウトすることで機能します。

#fe80::1%lo0    localhost

これで、localhostだけでなく、すべてのループバックホスト名が機能します。これどうしたの?

36
Nick Retallack

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

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

(その後、すべてが期待どおりに動作します)

24

まず、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/etc/hostsのランダムなlocalhostエントリに解決しようとし、@ NickRetallackが言及したように、そのエントリは、curlがデフォルトモードで解決するときにlocalhostによって選択されたものです(IPv6またはIPv4、最初に解決されるものは何でも)。

@_CharlesHebdoughが示唆するように、--ipv4モードで強制すると、curllocalhost127.0.0.1に解決します(/etc/hostslocalhostの他のIPv4エントリがないと仮定します)。

各実装は、必要に応じてlocalhostを解決するため、さまざまなツールで断続的に成功したのはなぜですか。

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

2
Jose Alban