Rails
Redis
localhost
IPv6
WEBRrick

ホスト名"localhost"でローカルサーバーに接続できない問題いろいろ(主にWindows環境)

More than 1 year has passed since last update.


はじめに

開発中のWebアプリには"localhost"というホスト名で接続するのが一般的ですが、昨今のIPv6のOSサポートにより、いろいろな問題が起きるようになりました。

※ 本記事の再現環境はWindows 10 Proです。Linuxなどの環境では現象は異なるかもしれません。


詳細はいいから、今すぐ解決したい場合


  • localhost というホスト名でローカルサーバーに繋らないと思ったら、代わりに 127.0.0.1 を使用してください。恐らく問題は解決します。


詳細

ここからが本記事の本編です。詳細を知りたい人は読んでください。抽象的な説明は避け、実際に遭遇した現象で説明します。


ホスト名 "localhost" とは

かつて、IPv4しか無い時代には "localhost" とは 127.0.0.1 (ループバックデバイス)であることに疑いはありませんでした。

OSがIPv6をサポートした今では、"localhost" は 127.0.0.1(IPv4アドレス) と ::1(IPv6アドレス) の両方を指します。

これがいろいろな問題を引き起こします。


遭遇した問題


Rubygemsのredisクライアントから "localhost" で接続するとredis-serverに接続できない

redis-cli からは "localhost"を使って接続できるので、かなりわかりにくい現象です。

原因は次のようなことだと推測できます。


  • 事実:Windowsのredis-serverは 127.0.0.1:6379 のみlistenしており ::1:6379 は listenしていません。


  • 推測:Rubyのクライアントは "localhost" は ::1:6379 のみを使う。redis-cliは 127.0.0.1:6379 を使う。



RubyのWEBrickで起動したHTTPサーバーに Google Chrome Extensionから http://localhost/ で接続するとconnectに3秒かかる

実際には次のようになります。

1回目は即connectする。

2回目は3秒かけてconnectする。
3回目は即connectする。
4回目は3秒かけてconnectする。この繰り返しとなります。
.
.


  • 事実:WEBRrickは 0.0.0.0:80 をlistenしている。(0.0.0.0はIPv4の全てアドレスという意味。つまりIPv6ではlistenしていない)


  • 推測:Google Chromeは localhostを 127.0.0.1 と ::1 に解決し、127.0.0.1 と ::1 をラウンドロビンで使う。もし繋がらない場合は3秒タイムアウトで次のIPアドレスを試している。



RubyのWEBrickで起動したHTTPサーバーに Emacsの内蔵HTTPクライアントから接続できない

詳細は説明しませんが、恐らく localhost が ::1 に解決されるのでしょう。


さいごに

この記事のような現象はサーバーがIPv4とIPv6でlistenするようになるのが一般的になるまで発生し続けるのでしょう。