Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

IPv4 stack should be preferred to IPv6 #775

Closed
aselder opened this Issue · 13 comments

7 participants

@aselder

We're trying to move an application to JRuby and request.ip is failing with an "invalid address" error.

Looking into things, env["REMOTE_ADDR"] is set to '0:0:0:0:0:0:0:1%0'

IPAddr.new('0:0:0:0:0:0:0:1%0') blows up in all Ruby implementations.

When our app is running under MRI, env["REMOTE_ADDR"] is '127.0.0.1".

So somehow under JRuby, env["REMOTE_ADDR"] is being set to something that IPAddr can't parse.

OS X 10.8, JRuby 1.7.4, Rails 3.2.14

@likethesky

+1 Yes, this can be reproduced via Rails, using the following steps:

$ rvm jruby
$ rails new foo
$ cd foo
$ rails generate scaffold bar
$ bundle exec rake db:migrate
# Edit Gemfile to add: gem 'pry-rails'
# In bars_controller.rb#index, add this:
  format.html {
    binding.pry
  }
$ bundle exec rails server
# Hit localhost:3000/bars
# Go to your server (pry) window and type:
[1] pry(#<BarsController>)> RUBY_DESCRIPTION
=> "jruby 1.7.4 (1.9.3p392) 2013-05-16 2390d3b on Java HotSpot(TM) Client VM 1.6.0_45-b06-451-11M4406 [darwin-i386]"
[2] pry(#<BarsController>)> request.ip
=> "0:0:0:0:0:0:0:1%0"

This does not occur in MRI. In MRI (using WeBrick for both), you get "127.0.0.1" ...

Btw, this makes ipaddr blow up, if you're using that, with an "invalid address" error. See also rails/rails#3641 and charliesome/better_errors#144 for similar reports.

@atambo
Collaborator

Can you try running jruby with your JRUBY_OPTS set to:

export JRUBY_OPTS="-J-Djava.net.preferIPv4Stack=true"
@BrandonMathis

The option above does fix the issue and forced IPv4. I was having an issue running the better_errors gem and setting -J-Djava.net.preferIPv4Stack=true fixed the issue with getting an IPv6 ip in the request that jruby just could not handle.

Not sure how or why or what the solution is for this but its but atambo's JRUBY_OPT is a step towards a solution :+1:

Shouldn't jruby just set IPv4 preferred to true since MRI seems to always stick with IPv4?

@BrandonMathis BrandonMathis referenced this issue in charliesome/better_errors
Closed

More IPV6 and better_errors incompatability #144

@BanzaiMan BanzaiMan closed this issue from a commit
@BanzaiMan BanzaiMan Fix #775
Prefer IPv4 by default.
f323c80
@BanzaiMan BanzaiMan closed this in f323c80
@BanzaiMan BanzaiMan referenced this issue from a commit in jruby/jruby-launcher
@BanzaiMan BanzaiMan Fix jruby/jruby#775
Prefer IPv4 stack by default.
cf84481
@BanzaiMan
Owner

IPAddr does not seem to be IPv6-friendly; IPAddr.new('0:0:0:0:0:0:0:1%0') does blow up for MRI, too.

The JVM option java.net.preferIPV4Stack=true must be passed to the JVM before JRuby spins up.

This would be done via bin/jruby.{,ba}sh (see f323c80) and JRuby launcher (jruby/jruby-launcher@cf84481, which should be included in the upcoming 1.0.18 release).

@rlpowell

Absolutely overriding a user preference is uncool.

This point release of jruby-launcher broke the hell out of my carefully crafted automation.

Why? Because my VMs are IPv6 only. I have to have -Djava.net.preferIPv6Addresses=true (and, ideally, also -Djava.net.preferIPv6Stack=true ) or nothing works. With those set, everything was working fine, but with this latest point release, because of the position of JAVA_OPTS, I get:

/opt/jdk/bin/java -Djdk.home= -Djruby.home=/usr/local/rvm/rubies/jruby-1.6.8 -Djruby.script=jruby -Djruby.shell=/bin
/sh -Djffi.boot.library.path=/usr/local/rvm/rubies/jruby-1.6.8/lib/native:/usr/local/rvm/rubies/jruby-1.6.8/lib/native/ppc-Linux:/usr/local/rvm/rubies/jruby-1.6.8/lib/native/i386-Linux:/usr/local/rvm/rubies/jruby-
1.6.8/lib/native/x86_64-Linux -Dsun.java.command=org.jruby.Main -cp -Xbootclasspath/a:/usr/local/rvm/rubies/jruby-1.6.8/lib/jruby.jar -Djava.net.preferIPv6Addresses=true -Xms64m -Xmx1024m -Xss1024k -Djava.net.pre
ferIPv4Stack=true org/jruby/Main /usr/local/rvm/rubies/jruby-1.6.8/bin/gem install -V --debug rubygems-update -v 1.3.5

(not the double "prefer" option, with the IPv4 one appearing later), and nothing works.

If I copy that command line exactly, but remove the -Djava.net.preferIPv4Stack=true bit, everything works fine.

I suggest that you:

  1. You move the -Djava.net.preferIPv4Stack=true bit to before the JAVA_OPTS section

  2. You detect any java.net.prefer that's already there, and if there is one, you don't set this option

  3. Both

This took me basically an entire work day to debug, so I'm pretty cranky right now. Again: silently overriding a stated user preference is not cool. Please don't do it.

@rlpowell

Since rvm appears to insist on installing the latest version of jruby-launcher, and since jruby-launcher, once installed, now prevents all remote operations, including gem installs, so I can't fix it, I actually don't even know how to work around this besides manually editing out the offending line. Any suggestions as to how I can get rvm to install an older jruby-launcher during its jruby install would be welcome.

@BanzaiMan
Owner

@rlpowell Good points. I will figure out a better solution. Sorry for the trouble.

@BanzaiMan BanzaiMan reopened this
@rlpowell

:) That was very kind of you, thank you.

In the meantime, here's what I added to my automation in case anyone else hits this issue:

sed -i "/Djava.net.preferIPv4Stack=true/d" $(ls -drt /usr/local/rvm/gems/jruby-1.6.8\@global/gems/jruby-launcher-* | tail -n 1)/argparser.cpp ; cd $(ls -drt /usr/local/rvm/gems/jruby-1.6.8\@glo
bal/gems/jruby-launcher-* | tail -n 1) ; make ; make install

FWIW, I agree that in every case except a pure IPv6-only machine, this solution was correct.

@headius headius closed this issue from a commit in jruby/jruby-launcher
@headius headius Revert "Fix jruby/jruby#775"
This reverts commit cf84481.
f77f6f9
@headius
Owner

This is still not fixed, but I have pushed a jruby-launcher 1.0.19 that reverts the hardcoding of preferIPv4Stack.

It seems like the truly correct fix would be to fix the offending libraries to handle IPv6 properly, but that's a bigger job. For now the workaround of specifying the property may be best, either via a -J-D flag to JRuby or the JAVA_OPTS env var.

@headius headius reopened this
@rlpowell
@headius
Owner

@rlpowell We have done that for other properties like file.encoding (hardcoded to UTF-8 on Mac unless specified), so there's precedent. @BanzaiMan maybe you can try to duplicate the file.encoding logic for the preferIPv4Stack property?

@BanzaiMan BanzaiMan closed this issue from a commit
@BanzaiMan BanzaiMan Add ability to set preferred network stack
Set the preferred IP network stack at runtime, using the extended
property `net.preferIPv4`, with the default being `true`.

This fixes #775 without involving `jruby-launcher`.
691bf16
@BanzaiMan BanzaiMan closed this in 691bf16
@BanzaiMan
Owner

You can now use the net.preferIPv4 property to set the preferred IP network stack version.

$ jruby -v -Xnet.preferIPv4=false -e 'puts java.lang.System.getProperty("java.net.preferIPv4Stack")'
jruby 1.7.5.dev (1.9.3p392) 2013-09-04 ed7fe67 on Java HotSpot(TM) 64-Bit Server VM 1.7.0_25-b15 [darwin-x86_64]
false

Note that java.net.preferIPv6Addresses is untouched, and that jruby-launcher upgrade is not required.

@rlpowell
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.