https://redmine.ruby-lang.org/
https://redmine.ruby-lang.org/favicon.ico?1711330511
2012-10-13T00:07:36Z
Ruby Issue Tracking System
Ruby master - Bug #7100: WEBrick::HTTPServer.new で BindAddress を指定しない場合に必ず警告が記録される
https://redmine.ruby-lang.org/issues/7100?journal_id=30447
2012-10-13T00:07:36Z
ChultOch5 (Sho Morita)
morita-pub-ja@inz.sakura.ne.jp
<ul></ul><p>=begin<br>
私のところでも同様の症状が出ています。そういった警告が出る場合、WEBrick サーバーに IPv6 でアクセスできなくなってしまいます。また、環境によっては <a href="http://localhost:3000/" class="external">http://localhost:3000/</a> のように localhost を指定してもアクセス不能になってしまいます。(:BindAddress を明示的に指定すれば問題ないのですけれども…)</p>
<p>WEBrick のドキュメントには :BindAddress に関して</p>
<p>デフォルトの nil や "0.0.0.0", "::" などを指定した場合は使用可能なすべてのネットワークインターフェースに対して listen を開始します。</p>
<p>と書いてあるものの、実際には</p>
<ul>
<li>nil を指定すると使用可能なすべての IPv4 および IPv6 ネットワークインターフェースに対して listen する。</li>
<li>"0.0.0.0" を指定すると使用可能なすべての IPv4 ネットワークインターフェースに対してのみ listen する。</li>
<li>"::" を指定すると使用可能なすべての IPv6 ネットワークインターフェースに対してのみ listen する。(一部システムでは nil と指定したのと同様に、すべての IPv4 と IPv6 ネットワークインターフェースに対して listen する)</li>
</ul>
<p>となります。</p>
<p>一部のシステム(Linuxなど)では、IPv6 ワイルドカードアドレスである :: を bind すると、IPv6 ネットワークインターフェースだけではなく、IPv4 ネットワークインターフェースも bind されます。0.0.0.0 と :: を両方 bind しようとすると、後から bind した方が Address already in use(EADDRINUSE) エラーとなり失敗するため、IPv6 でのアクセスが行えなくなってしまいます。</p>
<ul>
<li><a href="http://www.a-k-r.org/pub/socket-rubykaigi2009.pdf" class="external">http://www.a-k-r.org/pub/socket-rubykaigi2009.pdf</a></li>
<li><a href="http://codezine.jp/article/detail/5395" class="external">http://codezine.jp/article/detail/5395</a></li>
<li>NEWS-1.9.2</li>
</ul>
<p>などによると、Ruby 1.9.2 で Socket にたくさん機能が追加され、IPv6 問題がだいぶ改善されたようです。そこで追加された Socket#ipv6only! を呼び出すと IPV6_V6ONLY ソケットオプションが有効になり、0.0.0.0 と :: の両方を bind する事ができるようになります。</p>
<p>しかし、現在 WEBrick が使用している TCPServer は従来からある API で、IPV6_V6ONLY ソケットオプションをセットしません。新しい API である Socket.tcp_server_sockets などは、必要に応じて Socket#ipv6only! を呼び出してくれます。</p>
<p>ですので、TCPServer.new ではなく Socket.tcp_server_sockets を使うようにするのが良いかと思ったのですが、TCPServer.new のオブジェクトと Socket.tcp_server_sockets のオブジェクトは一部互換性の無い部分があり、置き換えてしまうと WEBrick を利用する既存のソフトウェアで互換性問題が起こるのではないか心配です。</p>
<p>そこで、互換性の問題が起こらないように TCPServer を使うのを維持しつつ問題を修正しようとすると、</p>
<ul>
<li>:BindAddress == nil である場合に、:: を先に bind し、0.0.0.0 を後から bind (その際 EADDRINUSE が起きても無視)する。</li>
</ul>
<p>というようにすれば良いのではないかと思います。一応パッチを作ってみました。</p>
<a name="Index-libwebrickutilsrb"></a>
<h1 >Index: lib/webrick/utils.rb<a href="#Index-libwebrickutilsrb" class="wiki-anchor">¶</a></h1>
<p>--- lib/webrick/utils.rb (revision 37168)<br>
+++ lib/webrick/utils.rb (working copy)<br>
@@ -79,6 +79,15 @@<br>
Socket::AI_PASSIVE) # flag<br>
last_error = nil<br>
sockets = []</p>
<ul>
<li>
<pre><code> # If address == nil, Socket.getaddrinfo returns 2 entries, the
</code></pre>
</li>
<li>
<pre><code> # IPv4 wildcard address "0.0.0.0" and the IPv6 wildcard address "::".
</code></pre>
</li>
<li>
<pre><code> # On some systems, if you try to bind for both "0.0.0.0" and "::",
</code></pre>
</li>
<li>
<pre><code> # the later one will fails.
</code></pre>
</li>
<li>
<pre><code> # To workaround such behaviour, try bind for "::" first, then
</code></pre>
</li>
<li>
<pre><code> # bind "0.0.0.0" and ignore EADDRINUSE error.
</code></pre>
</li>
<li>
<pre><code> if address.nil?
</code></pre>
</li>
<li>
<pre><code> res = res.sort_by{|i| i[4]}.reverse
</code></pre>
</li>
<li>
<pre><code> end
res.each{|ai|
begin
logger.debug("TCPServer.new(#{ai[3]}, #{port})") if logger
</code></pre>
</li>
</ul>
<p>@@ -87,7 +96,9 @@<br>
Utils::set_close_on_exec(sock)<br>
sockets << sock<br>
rescue => ex</p>
<ul>
<li>
<pre><code> logger.warn("TCPServer Error: #{ex}") if logger
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> logger.warn("TCPServer Error: #{ex}") if logger and !(address.nil? and
</code></pre>
</li>
<li>
<pre><code> ai[4] == Socket::AF_INET and
</code></pre>
</li>
<li>
<pre><code> Errno::EADDRINUSE === ex)
last_error = ex
end
}
</code></pre>
</li>
</ul>
<p>ちなみに、根本的な解決にはなりませんが、</p>
<a name="sysctl-netipv6bindv6only1"></a>
<h1 >sysctl net.ipv6.bindv6only=1<a href="#sysctl-netipv6bindv6only1" class="wiki-anchor">¶</a></h1>
<p>とすると、IPV6_V6ONLY ソケットオプションがデフォルトで有効になり、:BindAddress が nil でも警告は出なくなります。</p>
<p>=end</p>
Ruby master - Bug #7100: WEBrick::HTTPServer.new で BindAddress を指定しない場合に必ず警告が記録される
https://redmine.ruby-lang.org/issues/7100?journal_id=32403
2012-11-05T21:37:12Z
mame (Yusuke Endoh)
mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>akr (Akira Tanaka)</i></li><li><strong>Target version</strong> set to <i>2.0.0</i></li></ul><p>akr さん、どう思われますか?</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p>
Ruby master - Bug #7100: WEBrick::HTTPServer.new で BindAddress を指定しない場合に必ず警告が記録される
https://redmine.ruby-lang.org/issues/7100?journal_id=32481
2012-11-06T18:53:21Z
akr (Akira Tanaka)
akr@fsij.org
<ul></ul><p>2012/11/5 mame (Yusuke Endoh) <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a>:</p>
<blockquote>
<p>akr さん、どう思われますか?</p>
</blockquote>
<p>IPv4-mapped IPv6 address はプラットフォームによって利用できたりできなかったりするので、<br>
どのプラットフォームでも利用しないで動作するようにするのが動作が一貫してよいと思います。</p>
<p>私は、長期的には、TCPServer とかを使うのはやめて、<br>
Socket に移行して欲しいと思っていますが、<br>
互換性の問題を無視することもできませんよね。</p>
<h2>というふたつの点を考えると、Socket.tcp_server_sockets でソケットを作って、<br>
そこから TCPServer.for_fd で TCPServer のインスタンスを作るあたりかなぁ、と<br>
思います。</h2>
<p>[田中 哲][たなか あきら][Tanaka Akira]</p>
Ruby master - Bug #7100: WEBrick::HTTPServer.new で BindAddress を指定しない場合に必ず警告が記録される
https://redmine.ruby-lang.org/issues/7100?journal_id=32549
2012-11-07T19:19:16Z
akr (Akira Tanaka)
akr@fsij.org
<ul><li><strong>File</strong> <a href="/attachments/3219">webrick-dont-use-ipv4-mapped-ipv6-address.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/3219/webrick-dont-use-ipv4-mapped-ipv6-address.patch">webrick-dont-use-ipv4-mapped-ipv6-address.patch</a> added</li></ul><p>webrick-dont-use-ipv4-mapped-ipv6-address.patch みたいなかんじかなぁ。</p>
Ruby master - Bug #7100: WEBrick::HTTPServer.new で BindAddress を指定しない場合に必ず警告が記録される
https://redmine.ruby-lang.org/issues/7100?journal_id=36535
2013-02-18T23:54:43Z
mame (Yusuke Endoh)
mame@ruby-lang.org
<ul><li><strong>Target version</strong> changed from <i>2.0.0</i> to <i>2.6</i></li></ul><p>ちょっと今からだと怖すぎるのと、BindAddress を指定するという workaround があるようなので、<br>
すみませんが一旦 next minor に。<br>
2.0.0-pXXX で直すかどうかは nagachika さんにお任せします。</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p>
Ruby master - Bug #7100: WEBrick::HTTPServer.new で BindAddress を指定しない場合に必ず警告が記録される
https://redmine.ruby-lang.org/issues/7100?journal_id=37248
2013-03-02T17:36:18Z
akr (Akira Tanaka)
akr@fsij.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li></ul><p>This issue was solved with changeset r39551.<br>
Sho, thank you for reporting this issue.<br>
Your contribution to Ruby is greatly appreciated.<br>
May Ruby be with you.</p>
<hr>
<ul>
<li>lib/webrick/utils.rb: use Socket.tcp_server_sockets to create server<br>
sockets.<br>
fix [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: WEBrick::HTTPServer.new で BindAddress を指定しない場合に必ず警告が記録される (Closed)" href="https://redmine.ruby-lang.org/issues/7100">#7100</a>] <a href="https://bugs.ruby-lang.org/issues/7100" class="external">https://bugs.ruby-lang.org/issues/7100</a><br>
reported by sho-h (Sho Hashimoto).</li>
</ul>