2

I was writing a test where I wanted an HTTP server to listen on a random port and then connect to this port. I wrote:

mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Println("foo")
})

listener, err := net.Listen("tcp", ":0")
fmt.Println(err)

httpServer := &http.Server{Handler: mux}
go httpServer.Serve(listener)

fmt.Println("http://" + listener.Addr().String())  

r, err := http.Get("http://" + listener.Addr().String())
fmt.Println(r)
fmt.Println(err)

I meant to write net.Listen("tcp", "127.0.0.1:0") but accidentally wrote net.Listen("tcp", ":0").

For "http://" + listener.Addr().String() it prints:

http://[::]:1709

where as far as I understand the "bracket colon colon bracket" means "all interfaces".

To my surprise, the http.Get("http://[::]:1709") works, it connects to the webserver and "foo" is printed.

How is "http://[::]:1709" a valid address?

AndreKR
  • 32,613
  • 18
  • 106
  • 168

1 Answers1

3

At least on a Linux system, this results in a connection being made to localhost.

The address :: is IN6ADDR_ANY, typically used when listening to listen for connections to any IPv6 address on the system. It's analogous to INADDR_ANY, also known as 0.0.0.0 in IPv4.

Occasionally someone attempts to use one of these addresses as the destination address for an outgoing connection. When this happens:

When making an outgoing connection to 0.0.0.0, Linux actually connects from 127.0.0.1 to 127.0.0.1.

Similarly, when making an outgoing connection to ::, Linux actually connects from ::1 to ::1. Here is an example, taken from one of my websites (which happens to be an IP address lookup tool):

[error@murloc ~]$ curl -k -H "Host: myip.addr.space" https://[::]:8443/
::1

For completeness, here is the IPv4 version:

[error@murloc ~]$ curl -k -H "Host: myip.addr.space" https://0.0.0.0:8443/
127.0.0.1

Note that this is OS-specific. You would have received an error on Windows.

Michael Hampton
  • 9,737
  • 4
  • 55
  • 96