MacOS – How to make Ruby net::http stop stalling on ipv6

ipv6macosNetworkruby

There are some tools critical to my workflow that talk to www.pivotaltracker.com using ruby.

Some combination of updating from Ruby 2.1.2 to Ruby 2.1.3, recent os x system updates, and brew updates caused them to start taking a very long time to function, and the reason is ipv6, which I can see by using curl to make similar api requests:

    curl -v -H "X-TrackerToken: $TOKEN" -X GET http://www.pivotaltracker.com/services/v3/projects
    * About to connect() to www.pivotaltracker.com port 80 (#0)
    *   Trying 2607:f700:1:1388:c856:ed01:e1bf:b0e0…

after a minute or two of timing out on all of www.pivotaltracker.com's ipv6 addresses, the ipv4 address is eventually tried, and the request completes sucessfully.

This is despite using sudo networksetup -setv6off Ethernet and verifying that ipv6 was "off" in Preferences>Networking. I've also tried putting a correct ipv4 entry in my /etc/hosts.

If I use curl --ipv4 the request completes immediately. However I can't figure out how to force ruby scripts that use net::http to skip ipv6

The deeply frustrating thing about this is that the same issue happened with a round of development environment upgrades in May or June, and I somehow resolved it, but I can't seem to re-discover how or find it by looking through my shell history files.

The issue is not unique to pivotaltracker.com, but is true of any domain that has ipv6 addresses. Os X tries the ipv6 addresses first unless told to do otherwise, which browsers and some other apps seem to do, but ruby and most unix apps do not. wget stalls as well.

I will eventually upgrade my router and get ipv6 working completely, but in the meantime I would like to find a workaround.

Output of ifconfig

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=3<RXCSUM,TXCSUM>
    inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
    inet 127.0.0.1 netmask 0xff000000
    inet6 ::1 prefixlen 128
    inet6 fd3e:fe65:5a2c:ebe1:224:1dff:fe16:65d3 prefixlen 128
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether 00:24:1d:16:65:d3
    inet 192.168.0.47 netmask 0xffffff00 broadcast 192.168.0.255
    media: autoselect (1000baseT <full-duplex>)
    status: active
fw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 2030
    lladdr 00:19:a1:fa:00:00:24:1d
    media: autoselect <full-duplex>
    status: inactive
vnic0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=3<RXCSUM,TXCSUM>
    ether 00:1c:42:00:00:08
    inet 10.211.55.2 netmask 0xffffff00 broadcast 10.211.55.255
    inet6 fe80::21c:42ff:fe00:8%vnic0 prefixlen 64 scopeid 0x6
    inet6 ::1 prefixlen 64
    media: autoselect
    status: active
vnic1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=3<RXCSUM,TXCSUM>
    ether 00:1c:42:00:00:09
    inet 10.37.129.2 netmask 0xffffff00 broadcast 10.37.129.255
    inet6 fe80::21c:42ff:fe00:9%vnic1 prefixlen 64 scopeid 0x7
    inet6 ::1 prefixlen 64
    media: autoselect
    status: active

netstat -r

when I run netstat -r, it has an Internet6 section, despite System Preferences>Network>Ethernet>Advanced…>Configure IPv6 being set to Off.

Best Answer

I am not sure that this is an Apple issue, but a Ruby issue. You can see a bug report here.

You might try specifying a ipv6-specific hostname upon initialization.

For example, TCPServer.new('::1', pivotal_tracker_address) should allow you to use curl without specifying the -ipv6. I can't see you Ruby code, so I am not sure if this will fix your problem.

Hope this helps.