ginuerzh/gost · error

peer connect failure

Error message

peer connect failure

What it means

waitConnectSOCKS5 returns 'peer connect failure' when the remote SOCKS5 relay answered the CONNECT for the peer (client behind NAT) with a non-Succeeded reply code. The remote relay reached the relay, but the relay could not establish the connection to the peer endpoint (rep.Rep carries the SOCKS5 failure reason).

Source

Thrown at forward.go:578

		log.Log("[rtcp] SOCKS5 BIND reply: ", err)
		return nil, err
	}
	conn.SetReadDeadline(time.Time{})
	if rep.Rep != gosocks5.Succeeded {
		log.Logf("[rtcp] bind on %s failure", l.addr)
		return nil, fmt.Errorf("Bind on %s failure", l.addr.String())
	}
	log.Logf("[rtcp] BIND ON %s OK", rep.Addr)

	// second reply, peer connected
	rep, err = gosocks5.ReadReply(conn)
	if err != nil {
		log.Log("[rtcp]", err)
		return nil, err
	}
	if rep.Rep != gosocks5.Succeeded {
		log.Logf("[rtcp] peer connect failure: %d", rep.Rep)
		return nil, errors.New("peer connect failure")
	}

	log.Logf("[rtcp] PEER %s CONNECTED", rep.Addr)
	return conn, nil
}

func (l *tcpRemoteForwardListener) Addr() net.Addr {
	if l.ln != nil {
		return l.ln.Addr()
	}
	return l.addr
}

func (l *tcpRemoteForwardListener) Close() error {
	if l.ln != nil {
		return l.ln.Close()
	}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Check the remote log line '[rtcp] peer connect failure: <code>' for the exact SOCKS5 reply code
  2. Verify the peer (client behind NAT) is running and listening on the expected port
  3. Fix firewall/NAT rules on the peer side allowing the relay's inbound connection
  4. Confirm remote relay node connectivity and that its egress permits reaching the peer

Example fix

// before
conn, err := l.waitConnectSOCKS5(...) // opaque failure
// after
conn, err := l.waitConnectSOCKS5(...)
if err != nil {
    if err.Error() == "peer connect failure" {
        // inspect remote logs for rep.Rep; retry after peer is reachable
        return nil, fmt.Errorf("peer connect failure (rep=%d): retry after peer reachable", lastRep)
    }
    return nil, err
}
Defensive patterns

Strategy: retry

Validate before calling

// before accepting a rtcp tunnel, verify peer reachability
conn, err := net.DialTimeout("tcp", peerAddr, 5*time.Second)
if err != nil {
    return fmt.Errorf("peer %s not reachable before tunnel setup: %w", peerAddr, err)
}

Type guard

func isPeerConnectFailure(err error) bool {
    return err != nil && err.Error() == "peer connect failure"
}

Try / catch

conn, err := l.Accept()
if err != nil {
    if isPeerConnectFailure(err) {
        // inspect remote 'peer connect failure: <rep>' log, wait, then retry
        time.Sleep(backoff)
        return retry()
    }
    return err
}

Prevention

When it happens

Trigger: Accepting a remote port-forward (rtcp) where the remote server's SOCKS5 CONNECT reply rep.Rep != gosocks5.Succeeded — e.g. host unreachable, connection refused, or not allowed on the remote side.

Common situations: NAT hole-punching for reverse tunnels where the client-side peer is down, firewall blocks the remote relay to peer hop, wrong peer port in rtcp config, remote relay lacks outbound access.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/37d341f828f81149. Report an issue: GitHub.