Skip to content

issue(network): go - tcp dial behavior mismatch (unexpected failures) #2069

@rinor

Description

@rinor
  • config.json
{
  "Dirs": [ "etc" ]
}
  • cat etc/hosts
127.0.0.1   localhost
::1         localhost
  • ops run -c config.json netdial
running local instance
booting /home/rinor/.ops/images/netdial ...
en1: assigned 10.0.2.15
en1: assigned FE80::F038:1DFF:FEE4:97DC

Listen tcp4/6: [::]:58530
Listen tcp4  : 0.0.0.0:58531
Listen tcp6  : [::]:58532

Listener provided IP:PORT - dial

dialer.Dial(tcp?, [::]:58530)		net.Dial: dial tcp [::]:58530: i/o timeout
dialer.Dial(tcp4, 0.0.0.0:58531)	net.Dial: dial tcp4 0.0.0.0:58531: connect: connection reset by peer
dialer.Dial(tcp6, [::]:58532)		net.Dial: dial tcp6 [::]:58532: i/o timeout

:PORT - dial

dialer.Dial(tcp?, :58530)		net.Dial: dial tcp :58530: connect: connection reset by peer
dialer.Dial(tcp4, :58531)		net.Dial: dial tcp4 :58531: connect: connection reset by peer
dialer.Dial(tcp6, :58532)		net.Dial: dial tcp6 :58532: i/o timeout

127.0.0.1:PORT - dial

dialer.Dial(tcp?, 127.0.0.1:58530)	TCP? connection established:	127.0.0.1:58530	<- 127.0.0.1:58539
dialer.Dial(tcp4, 127.0.0.1:58531)	TCP4 connection established:	127.0.0.1:58531	<- 127.0.0.1:58540
dialer.Dial(tcp6, [::1]:58532)		TCP6 connection established:	[::1]:58532	<- [::1]:58541

localhost:PORT - dial (needs /etc/hosts)

dialer.Dial(tcp?, localhost:58530)	TCP? connection established:	127.0.0.1:58530	<- 127.0.0.1:58542
dialer.Dial(tcp4, localhost:58531)	TCP4 connection established:	127.0.0.1:58531	<- 127.0.0.1:58543
dialer.Dial(tcp6, localhost:58532)	TCP6 connection established:	[::1]:58532	<- [::1]:58544
  • ./netdial - on linux
Listen tcp4/6: [::]:36231
Listen tcp4  : 0.0.0.0:46819
Listen tcp6  : [::]:34691

Listener provided IP:PORT - dial

dialer.Dial(tcp?, [::]:36231)		TCP? connection established:	[::1]:36231	<- [::1]:48372
dialer.Dial(tcp4, 0.0.0.0:46819)	TCP4 connection established:	127.0.0.1:46819	<- 127.0.0.1:43712
dialer.Dial(tcp6, [::]:34691)		TCP6 connection established:	[::1]:34691	<- [::1]:49164

:PORT - dial

dialer.Dial(tcp?, :36231)		TCP? connection established:	127.0.0.1:36231	<- 127.0.0.1:59636
dialer.Dial(tcp4, :46819)		TCP4 connection established:	127.0.0.1:46819	<- 127.0.0.1:44074
dialer.Dial(tcp6, :34691)		TCP6 connection established:	[::1]:34691	<- [::1]:45546

127.0.0.1:PORT - dial

dialer.Dial(tcp?, 127.0.0.1:36231)	TCP? connection established:	127.0.0.1:36231	<- 127.0.0.1:59644
dialer.Dial(tcp4, 127.0.0.1:46819)	TCP4 connection established:	127.0.0.1:46819	<- 127.0.0.1:44082
dialer.Dial(tcp6, [::1]:34691)		TCP6 connection established:	[::1]:34691	<- [::1]:45552

localhost:PORT - dial (needs /etc/hosts)

dialer.Dial(tcp?, localhost:36231)	TCP? connection established:	[::1]:36231	<- [::1]:60582
dialer.Dial(tcp4, localhost:46819)	TCP4 connection established:	127.0.0.1:46819	<- 127.0.0.1:44088
dialer.Dial(tcp6, localhost:34691)	TCP6 connection established:	[::1]:34691	<- [::1]:45560
  • go build -ldflags "-s -w" -tags "netgo" -trimpath -o bin/netdial main.go
package main

import (
	"fmt"
	"net"
	"os"
	"strconv"
	"time"
)

func main() {
	// TCP - listener (both tcp4/tcp6)
	nl, err := net.Listen("tcp", ":0")
	if err != nil {
		fmt.Println("Error net.Listen:", err)
		os.Exit(1)
	}

	go func() {
		for {
			conn, err := nl.Accept()
			if err != nil {
				fmt.Println("Error accepting TCP connection:", err)
				continue
			}
			go func() {
				defer conn.Close()
				fmt.Printf("TCP? connection established:\t%s\t<- %s\n", conn.LocalAddr(), conn.RemoteAddr())
			}()
		}
	}()

	// TCP4
	nl4, err := net.Listen("tcp4", ":0")
	if err != nil {
		fmt.Println("Error net.Listen:", err)
		os.Exit(1)
	}
	go func() {
		for {
			conn, err := nl4.Accept()
			if err != nil {
				fmt.Println("Error accepting TCP4 connection:", err)
				continue
			}
			go func() {
				defer conn.Close()
				fmt.Printf("TCP4 connection established:\t%s\t<- %s\n", conn.LocalAddr(), conn.RemoteAddr())
			}()
		}
	}()

	// TCP6
	nl6, err := net.Listen("tcp6", ":0")
	if err != nil {
		fmt.Println("Error net.Listen:", err)
		os.Exit(1)
	}
	go func() {
		for {
			conn, err := nl6.Accept()
			if err != nil {
				fmt.Println("Error accepting TCP6 connection:", err)
				continue
			}
			go func() {
				defer conn.Close()
				fmt.Printf("TCP6 connection established:\t%s\t<- %s\n", conn.LocalAddr(), conn.RemoteAddr())
			}()
		}
	}()

	time.Sleep(2 * time.Second)

	dialer := net.Dialer{Timeout: 100 * time.Millisecond}

	fmt.Println()
	fmt.Println("Listen tcp4/6:", nl.Addr().String())
	fmt.Println("Listen tcp4  :", nl4.Addr().String())
	fmt.Println("Listen tcp6  :", nl6.Addr().String())
	fmt.Println()
	fmt.Println("Listener provided IP:PORT - dial")

	for i := 0; i < 1; i++ {
		fmt.Println()

		// TCP
		fmt.Printf("dialer.Dial(%s, %s)\t\t", "tcp?", nl.Addr().String())
		c, err := dialer.Dial("tcp", nl.Addr().String())
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP4
		fmt.Printf("dialer.Dial(%s, %s)\t", "tcp4", nl4.Addr().String())
		c4, err := dialer.Dial("tcp4", nl4.Addr().String())
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c4.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP6
		fmt.Printf("dialer.Dial(%s, %s)\t\t", "tcp6", nl6.Addr().String())
		c6, err := dialer.Dial("tcp6", nl6.Addr().String())
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c6.Close()
		}
		time.Sleep(200 * time.Millisecond)
	}

	// port only dial

	fmt.Println()
	fmt.Println(":PORT - dial")

	for i := 0; i < 1; i++ {
		fmt.Println()

		// TCP
		tcpAddr := nl.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, :%d)\t\t", "tcp?", tcpAddr.Port)
		c, err := dialer.Dial("tcp", ":"+strconv.Itoa(tcpAddr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP4
		tcp4Addr := nl4.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, :%d)\t\t", "tcp4", tcp4Addr.Port)
		c4, err := dialer.Dial("tcp4", ":"+strconv.Itoa(tcp4Addr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c4.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP6
		tcp6Addr := nl6.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, :%d)\t\t", "tcp6", tcp6Addr.Port)
		c6, err := dialer.Dial("tcp6", ":"+strconv.Itoa(tcp6Addr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c6.Close()
		}
		time.Sleep(200 * time.Millisecond)
	}

	// local ip:port dial

	fmt.Println()
	fmt.Println("127.0.0.1:PORT - dial")

	for i := 0; i < 1; i++ {
		fmt.Println()

		// TCP
		tcpAddr := nl.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, 127.0.0.1:%d)\t", "tcp?", tcpAddr.Port)
		c, err := dialer.Dial("tcp", "127.0.0.1:"+strconv.Itoa(tcpAddr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP4
		tcp4Addr := nl4.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, 127.0.0.1:%d)\t", "tcp4", tcp4Addr.Port)
		c4, err := dialer.Dial("tcp4", "127.0.0.1:"+strconv.Itoa(tcp4Addr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c4.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP6
		tcp6Addr := nl6.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, [::1]:%d)\t\t", "tcp6", tcp6Addr.Port)
		c6, err := dialer.Dial("tcp6", "[::1]:"+strconv.Itoa(tcp6Addr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c6.Close()
		}
		time.Sleep(200 * time.Millisecond)
	}

	// localhost:port dial (needs /etc/hosts)

	fmt.Println()
	fmt.Println("localhost:PORT - dial (needs /etc/hosts)")

	for i := 0; i < 1; i++ {
		fmt.Println()

		// TCP
		tcpAddr := nl.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, localhost:%d)\t", "tcp?", tcpAddr.Port)
		c, err := dialer.Dial("tcp", "localhost:"+strconv.Itoa(tcpAddr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP4
		tcp4Addr := nl4.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, localhost:%d)\t", "tcp4", tcp4Addr.Port)
		c4, err := dialer.Dial("tcp4", "localhost:"+strconv.Itoa(tcp4Addr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c4.Close()
		}
		time.Sleep(200 * time.Millisecond)

		// TCP6
		tcp6Addr := nl6.Addr().(*net.TCPAddr)
		fmt.Printf("dialer.Dial(%s, localhost:%d)\t", "tcp6", tcp6Addr.Port)
		c6, err := dialer.Dial("tcp6", "localhost:"+strconv.Itoa(tcp6Addr.Port))
		if err != nil {
			fmt.Println("net.Dial:", err)
		} else {
			c6.Close()
		}
		time.Sleep(200 * time.Millisecond)
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions