trouble with http.ListenAndServe (can't connect remotely)

7,251 views
Skip to first unread message

David Roundy

unread,
Sep 6, 2010, 8:52:54 AM9/6/10
to golang-nuts
Hi all,

I've been having trouble with http.ListenAndServe(":12345", nil). I
can connect locally at http://localhost:12345, but don't seem to able
to connect from a remote machine. I suspect this relates to
configuration outside my go program, so this isn't perhaps the best
place to ask... but I don't know of a better place (I've done
relatively little network server programming or network-related
sysadminning). Any suggestions as to how to debug this?
--
David Roundy

Jeff Hodges

unread,
Sep 6, 2010, 3:18:18 PM9/6/10
to David Roundy, golang-nuts

Hey David! You've run into some adorable Network Programming 101 stuff. Using "localhost" or "127.0.0.1" as the hostname for your service makes it only available to socket connections coming from the same machine. "localhost" is the name that resolves to 127.0.0.1 which, in turn, is a special IP that only exists through the loopback interface.

Using "0.0.0.0" is the trivial way of allowing other machines to connect to your service. I can't remember what docs I used to learn this, but I've probably given you enough keywords to find out more. From a would-have-been physicist, good luck!

(Forgive the HTML formatting of this email. Can't convince my droid not to do it.)

David Roundy

unread,
Sep 6, 2010, 3:57:33 PM9/6/10
to Jeff Hodges, golang-nuts
I've tried using

err := http.ListenAndServe("0.0.0.0:12345", nil)

which I think ought to cause it to listen to everything, but still am
unable to connect remotely, just through localhost. :( The routing
tables can't be *too* messed up, since I am able to connect to apache
on port 80.

David

--
David Roundy

chris dollin

unread,
Sep 6, 2010, 4:04:55 PM9/6/10
to David Roundy, Jeff Hodges, golang-nuts
On 6 September 2010 20:57, David Roundy <rou...@physics.oregonstate.edu> wrote:
> I've tried using
>
>        err := http.ListenAndServe("0.0.0.0:12345", nil)
>
> which I think ought to cause it to listen to everything, but still am
> unable to connect remotely, just through localhost.  :(  The routing
> tables can't be *too* messed up, since I am able to connect to apache
> on port 80.

Port 80 might be explicitly allowed, whereas port 12345 might
be viewed with suspicion. On my local home network, if I serve
http on say port 3000, other machines can't access it, but if
I serve on 80, they can. And that's even when I've fiddled
with what claims its the firewall configuation GUI, so there's
clearly something I'm missing.

Chris

(Don't know what would happen if I tried 8080. Will do that
sometime.)

--
Chris "allusive" Dollin

Rob 'Commander' Pike

unread,
Sep 6, 2010, 5:39:04 PM9/6/10
to chris dollin, David Roundy, Jeff Hodges, golang-nuts
Indeed. Networks are conceptually far too simple not to be made
unusable by people adding confusing properties in order to leave their
mark on technology.

-rob

andrey mirtchovski

unread,
Sep 6, 2010, 5:52:52 PM9/6/10
to golang-nuts
what OS? what error does telnet blah 80 give?

if you're on most versions of linux that have a default firewall
blocking all ports you'll get 'no route to host'. "service iptables
stop" will give you some time before you find the gui system tool to
disable the port from the filtering chain.

again, that assumes a subset of the Linux versions out there.

David Roundy

unread,
Sep 6, 2010, 7:00:10 PM9/6/10
to andrey mirtchovski, golang-nuts
Hi Andrey,

Thanks for the suggestions!

I'm running Debian squeeze (living on the edge, as it were), which
doesn't evidently support "service iptables stop", but also I've never
heard that it had firewall rules installed by default (and I haven't
programmed any). I have apache running on port 80 (mostly just to
test this) and I can telnet to apache just fine (I typed "GET\n" to
verify that it's this particular machine, where I put the foobar in
the default /var/www/index.html), but I get connection refused on
`telnet 192.168.0.2 12345`. When I telnet to localhost, however, I
can reach either apache on port 80, or my program on port 12345 (which
for some reason doesn't respond when I just type "GET\n" in telnet).

As an additional test, I tried recompiling to listen on port 80 (and
run the go server as root), and I got the same results as listening
with my program on port 12345: I couldn't `telnet 192.168.0.2 80`,
but could connect with `telnet localhost 80`. I did remember to
disable apache before starting... actually I got a friendly error that
"listen tcp 0.0.0.0:80: address already in use" when I hadn't yet
stopped apache.

So it seems like it's something to do with the go code[1], but really
(I think) is bog-standard use of the http.package, and I'm puzzled why
apache is able to work when this code doesn't.

[1] http://github.com/droundy/bridge/blob/master/server.go

below is a transcript (probably useless) of my telnet testing, with my
server listening on port 12345, and apache listening on port 80:

collins:~$ telnet 192.168.0.2 12345
Trying 192.168.0.2...
telnet: Unable to connect to remote host: Connection refused
collins:~$ telnet 192.168.0.2 80
Trying 192.168.0.2...
Connected to 192.168.0.2.
Escape character is '^]'.
GET
<html><body><h1>It works, yay!</h1>

foobar

</body></html>
Connection closed by foreign host.
collins:~$ telnet localhost 12345
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET
Connection closed by foreign host.
collins:~$ telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET
<html><body><h1>It works, yay!</h1>

foobar

</body></html>
Connection closed by foreign host.

--
David Roundy

David Roundy

unread,
Sep 7, 2010, 7:15:46 AM9/7/10
to andrey mirtchovski, golang-nuts
Hi all,

I just tried running my server under strace, and saw something that
strikes me as suspicious:

socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 3
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
bind(3, {sa_family=AF_INET6, sin6_port=htons(12345),
inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0,
sin6_scope_id=0}, 28) = 0
getsockname(3, {sa_family=AF_INET6, sin6_port=htons(12345),
inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0,
sin6_scope_id=0}, [28]) = 0

This looks to me like my program is trying to use ipv6. Could this be
the trouble?

David

buggyserver.go

Russ Cox

unread,
Sep 7, 2010, 9:28:33 AM9/7/10
to David Roundy, andrey mirtchovski, golang-nuts
Yes. The workaround for now is

sysctl -w net.linuxisbroken.ipv6only = false

I might not have gotten the spelling right
but you can probably double check with the
output of sysctl -a.

Russ

David Roundy

unread,
Sep 7, 2010, 11:18:41 AM9/7/10
to r...@golang.org, andrey mirtchovski, golang-nuts
Thanks! For the archives (and others looking for a solution), what worked was:

sysctl -w net.ipv6.bindv6only=0

A little googling reveals that the default changed in Debian on the
upgrade to Squeeze, and that the netbase maintainers thing that
net.ipv6.bindv6only=1 is the default on all modern operating systems,
so it does seem like it'd be worth figuring out how to work around
this in the net package. Evidently, one can use setsockopt to set the
option on a per-socket basis, although I have no idea how this would
work.

David

g...@iparadigms.com

unread,
Nov 17, 2015, 8:42:43 PM11/17/15
to golang-nuts, r...@golang.org, mirtc...@gmail.com
Hi David, I just had the same problem. I just saw an example in the Go doc like "http.ListenAndServe(":8080", nil)", so I got rid of the address, and it worked for me. Have you tried this?

andrewc...@gmail.com

unread,
Nov 17, 2015, 9:05:03 PM11/17/15
to golang-nuts, r...@golang.org, mirtc...@gmail.com, g...@iparadigms.com
You have replied to a 5 year old issue, I am sure he solved his problem by now.
Reply all
Reply to author
Forward
0 new messages