cloudflare/cloudflared · error

not a tcp connection

Error message

not a tcp connection

What it means

ConnDialer.Dial inspects the underlying connection's LocalAddr and requires it to be a *net.TCPAddr to construct the AddrSpec reported to the SOCKS client. If the wrapped conn is not a TCP connection (e.g. Unix socket), Dial returns 'not a tcp connection'.

Source

Thrown at socks/dialer.go:52

}

// ConnDialer is like NetDialer but with an existing TCP dialer already created
type ConnDialer struct {
	conn net.Conn
}

// NewConnDialer creates a new dialer with a already created net.conn (TCP expected)
func NewConnDialer(conn net.Conn) Dialer {
	return &ConnDialer{
		conn: conn,
	}
}

// Dial is a TCP dialer but already created
func (d *ConnDialer) Dial(address string) (io.ReadWriteCloser, *AddrSpec, error) {
	local, ok := d.conn.LocalAddr().(*net.TCPAddr)
	if !ok {
		return nil, nil, fmt.Errorf("not a tcp connection")
	}

	addr := AddrSpec{IP: local.IP, Port: local.Port}
	return d.conn, &addr, nil
}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Serve the SOCKS handler on a TCP listener so conn.LocalAddr() is *net.TCPAddr.
  2. Remove the Unix socket/pipe wrapper for this handler.
  3. If a non-TCP transport is required, supply a dialer that can produce an AddrSpec without a TCP local address.
  4. Check how the conn passed into ConnDialer is created.

Example fix

// before
ln, _ := net.Listen("unix", "/tmp/socks.sock")
// after
ln, _ := net.Listen("tcp", "127.0.0.1:1080")
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := conn.LocalAddr().(*net.TCPAddr); !ok { return errors.New("socks handler requires TCP connection") }

Type guard

func isTCPConn(conn net.Conn) bool { _, ok := conn.LocalAddr().(*net.TCPAddr); return ok }

Try / catch

rwc, addr, err := dialer.Dial(address)
if err != nil {
    return fmt.Errorf("cannot determine local addr: %w", err)
}

Prevention

When it happens

Trigger: Serving the SOCKS handler over a listener whose accepted connections are not *net.TCPConn, then a client requests a BIND-style reply needing the local address.

Common situations: Wrapping the SOCKS handler behind a Unix socket or in-memory pipe; test harnesses using net.Pipe; unusual listener configurations.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/c8fae7733710d120. Report an issue: GitHub.