Sunday, February 22, 2015

IPv6 and IPv4 name resolution with Go

As part of a work-related project, I'm writing code that needs to resolve DNS names using Go, on illumos.

While doing this work, I noticed a very surprising thing.  When a host has both IPv6 and IPv4 addresses associated with a name (such as localhost), Go prefers to resolve to the IPv4 version of the name, unless one has asked specifically for v6 names.

This flies in the fact of existing practice on illumos & Solaris systems, where resolving a name tends to give an IPv6 result, assuming that any IPv6 address is plumbed on the system.  (And on modern installations, that is the default -- at least the loopback interface of ::1 is always plumbed by default.  And not only that, but services listening on that address will automatically serve up both v6 and v4 clients that connect on either ::1 or 127.0.0.1.)

The rationale for this logic is buried in the Go net/ipsock.go file, in comments for the function firstFavoriteAddr ():
    76			// We'll take any IP address, but since the dialing
    77			// code does not yet try multiple addresses
    78			// effectively, prefer to use an IPv4 address if
    79			// possible. This is especially relevant if localhost
    80			// resolves to [ipv6-localhost, ipv4-localhost]. Too
    81			// much code assumes localhost == ipv4-localhost.
This is a really surprising result.  If you want to get IPv6 names by default, with Go, you could use the net.ResolveIPAddr() (or ResolveTCPAddr() or ResolveUDPAddr()) functions with the network type of "ip6", "tcp6", or "udp6" first.  Then if that resolution fails, you can try the standard versions, or the v4 specific versions (doing the latter is probably slightly more efficient.)  Here's what that code looks like:
        name := "localhost"

        // First we try IPv6.  Note that we *hope* this fails if the host
        // stack does not actually support IPv6.
        err, ip := net.ResolveIP("ip6", name)
        if err != nil {
                // IPv6 not found, maybe IPv4?
                err, ip = net.ResolveIP("ip4", name)
        }
However, this choice turns out to also be evil, because while ::1 often works locally as an IPv6 address and is functional, other addresses, for example www.google.com, will resolve to IPv6 addresses which will not work unless you have a clean IPv6 path all the way through.  For example, the above gives me this for www.google.com: 2607:f8b0:4007:804::1010, but if I try to telnet to it, it won't work -- no route to host (of course, because I don't have an IPv6 path to the Internet, both my home gateway and my ISP are IPv4 only.)


Its kind of a sad that the Go people felt that they had to make this choice -- at some level it robs the choice from the administrator, and encourages the existing broken code to remain so.  I'm not sure what the other systems use, but at least on illumos, we have a stack that understands the situation, and resolves optimally for the given the situation of the user.  Sadly, Go shoves that intelligence aside, and uses its own overrides.

One moral of the story here is -- always use either explicit v4 or v6 addresses if you care, or ensure that your names resolve properly.

Wednesday, February 11, 2015

Rise of mangos

What is mangos?


Those of you who follow me may have heard about this project I've created called mangos.

Mangos is a lightweight messaging system designed to be wire compatible with nanomsg, but is implemented entirely in Go.

There is a very nice write up of mangos by Tyler Treat, which might help explain some things.

Recent Activity


As a consequence of a few things, the last two weeks has seen a substantial rise of use of mangos.

First off, there was Tyler's excellent article.  (By the way, he's done a series comparing and contrasting other messaging systems -- highly recommended reading.)

Second, mangos got mentioned on Hacker News.  That drew a large number visitors to my github repo.

Then another open source project, Goq, switched from using libnanomsg to mangos, using the compatibility shim I provided for such use.  As a consequence of that work, several bugs were identified, and subsequently squashed.

The upshot of all that is that I saw the number unique visitors sky rocket.  On Saturday Feb 7, there were over 2500 unique visitors to the github page, and 29 unique people took clones.  Sunday it tapered sharply to just over 1k visitors, and today there were only 7.  Peaks rarely get sharper than that.

Improvements


Over the past week or so I've made a large number of changes and improvements.  Recently, mangos has grown support for RFC 6455 (websocket), including websocket over TLS, and has had numerous internal improvements.

Some of these changes have broken API.  If you use mangos, I'm sorry about the breakage -- please let me know if you're hurt by this.  (I have created tagged releases for v1.0.0 and v1.1.0 in an attempt to mitigate the risk, but tip still has some interesting changes in it.)

Unlike libnanomsg, mangos (tip only) can notify you when a connection is added or removed, and you can access interesting information about the connection.  This is in the Port API.

Futures


We are using mangos internally at Lucera, and I know now of several cases of production use.  This is kind of scary at one level, since I wrote this originally as a hobby project about a year ago (to learn Go.)  But it has become useful -- frankly extending mangos is far far more pleasurable than working in the C libnanomsg implementation -- a lot of this is thanks to Go which is utterly pleasurable to work in (no matter how bad the guts may be reputed to be).  Being able to write a new TLS transport, or even websocket, in the course of an afternoon or two (actually for TLS it was more like an hour), is really nice.

I'm hoping that more people will find it useful, and that folks who want to experiment with the underlying messaging patterns may find it easier to work with than the C code.  Ideally, there will be more collaborators here, as we start exploring new directions for this stuff.

In the meantime, I'm going to continue to work to improve and extend mangos, because its become one of the tools at my day job.  Its nice when work and pleasure come together!