[go-nuts] comparing host names

60 views
Skip to first unread message

Petar Maymounkov

unread,
May 1, 2010, 7:47:57 PM5/1/10
to golang-nuts
I am implementing the HTTP server feature where one can
specify which hosts are allowed to issue HTTP requests.

Typically you want to specify, say e.g., "localhost" is allowed.

When a connection arrives via net.Accept, in principle one
should look at conn.RemoteAddr().String()
and check if it is in the list of allowed hosts.

The trouble is that there are a lot of ways to specify the same host.
E.g. "localhost" is the same as "127.0.0.1", and to make things
harder:
for a connection coming from localhost, the call to
conn.RemoteAddr.String()
produces something like "[::1]:61871".

Is there some systematic/preferred way to look at a string (like "[::
1]:61871")
and convert it to a canonical form, something like "127.0.0.1:61871"
so that then (after stripping the port number) you can actually
compare this
against other canonical hostnames.

Thanks,
--Petar

Petar Maymounkov

unread,
May 1, 2010, 7:58:36 PM5/1/10
to golang-nuts
What's unpleasant is that net.LookupHost() behaves like this:

on input "localhost", it returns {"127.0.0.1","::1"},
but on inputs "127.0.0.1" or "::1" it returns a DNS error.

One would expect that all three inputs return the same result.

Since the user enters their allowed hosts as a string,
the program should expect any of "127.0.0.1", "localhost" or "::1",
but LookupHost behaves differently on them.

--Petar

Russ Cox

unread,
May 1, 2010, 8:08:38 PM5/1/10
to Petar Maymounkov, golang-nuts
> on input "localhost", it returns {"127.0.0.1","::1"},
> but on inputs "127.0.0.1" or "::1" it returns a DNS error.
>
> One would expect that all three inputs return the same result.
>
> Since the user enters their allowed hosts as a string,
> the program should expect any of "127.0.0.1", "localhost" or "::1",
> but LookupHost behaves differently on them.

LookupHost is for looking up host names.
Other people might expect that looking up 127.0.0.1
should return "localhost" (the same way that
"host 18.26.4.9" behaves on the command line).

It sounds like the thing to do is pass the string specified
by the user ("localhost" or "127.0.0.1") to ParseIP.
If you get nil back, then try to resolve it as a host name
and add all the IP addresses you get back.

When you get the RemoteAddr() from the connection,
instead of calling String(), do an interface check to see
if it is a *net.TCPAddr (it will be). Then pull out the IP
field from that struct and compare against the list.

It appears that there is no IP comparison function in
package net. I'll add one later, but for now you can use

func EqualIP(x, y net.IP) bool {
return bytes.Equal(x.To16(), y.To16())
}

Russ

Petar Maymounkov

unread,
May 2, 2010, 3:23:33 PM5/2/10
to r...@golang.org, golang-nuts
When you get around to it, you might consider adding
hash codes (?) to IPs, because I suppose one would
want to put those IPs in a map ideally.

--P

Petar Maymounkov

unread,
May 2, 2010, 7:31:41 PM5/2/10
to r...@golang.org, golang-nuts
Another problem you might want to know about:

There is no function in net that knows how to remove ports
from hostnames, if present. That surely is non-trivial given the differing
syntax between hostname:port, ipv4:port and ipv6::port.

--Petar
Reply all
Reply to author
Forward
0 new messages