txthinking/brook · error

dst too long

Error message

dst too long

What it means

NewSimpleStreamClient rejects a destination address whose encoded length exceeds 2048-32-2-4 (2010) bytes, because the fixed 2048-byte handshake buffer must hold the 32-byte password hash, 2-byte length prefix, 4-byte timestamp, and the dst address. dst longer than that would overflow the buffer, so the constructor fails fast.

Source

Thrown at simplestreamclient.go:41

	"github.com/txthinking/socks5"
	"github.com/txthinking/x"
)

type SimpleStreamClient struct {
	Server  net.Conn
	Timeout int
	RB      []byte
	WB      []byte
	network string
	src     string
	dst     string
}

func NewSimpleStreamClient(network string, password []byte, src string, server net.Conn, timeout int, dst []byte) (Exchanger, error) {
	c := &SimpleStreamClient{network: network, Server: server, Timeout: timeout, src: src, dst: socks5.ToAddress(dst[0], dst[1:len(dst)-2], dst[len(dst)-2:])}
	if len(dst) > 2048-32-2-4 {
		return nil, errors.New("dst too long")
	}
	b := x.BP2048.Get().([]byte)
	binary.BigEndian.PutUint16(b[32:32+2], uint16(4+len(dst)))
	i := time.Now().Unix()
	if c.network == "tcp" && i%2 != 0 {
		i += 1
	}
	if c.network == "udp" && i%2 != 1 {
		i += 1
	}
	binary.BigEndian.PutUint32(b[32+2:32+2+4], uint32(i))
	copy(b[:32], password)
	copy(b[32+2+4:], dst)
	if _, err := server.Write(b[:32+2+4+len(dst)]); err != nil {
		x.BP2048.Put(b)
		return nil, err
	}
	if c.network == "tcp" {

View on GitHub (pinned to 5cd13ef3b1)

Solutions

  1. Shorten the destination hostname or use an IP address literal instead of a very long name
  2. Validate/limit the dst address length before constructing the client and reject oversized requests earlier
  3. Check that dst bytes are a well-formed SOCKS5 address (ATYP + addr + port); a malformed slice with trailing garbage inflates the length
  4. If legitimate long destinations are required, use a protocol variant with a larger buffer

Example fix

// before
if len(dst) > 2048 { /* no check, just send */ }
// after
if len(dst) > 2048-32-2-4 {
    return nil, errors.New("dst too long")
}
cl, err := NewSimpleStreamClient(network, password, src, server, timeout, dst)
Defensive patterns

Strategy: validation

Validate before calling

if len(dst) > 2048-32-2-4 {
    return fmt.Errorf("destination address too long: %d bytes (max %d)", len(dst), 2048-32-2-4)
}

Try / catch

cl, err := NewSimpleStreamClient(network, password, src, server, timeout, dst)
if err != nil {
    if err.Error() == "dst too long" {
        return nil, fmt.Errorf("cannot proxy to %q: address exceeds protocol limit", dst)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling NewSimpleStreamClient (directly or via CreateExchanger/TCPHandle/UDPHandle) with a dst byte slice that, after socks5.ToAddress encoding, is longer than 2010 bytes — typically a very long hostname or an oversized crafted address blob.

Common situations: Proxying to hosts with abnormally long DNS names (near the 253-char DNS limit times overhead is still fine — real cases come from malformed/corrupt upstream address bytes or hostile clients sending giant address fields).

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06). Data as JSON: /api/errors/1c998550aaa44dd3. Report an issue: GitHub.