txthinking/brook · error

Expired request

Error message

Expired request

What it means

The packet server's Handle method decrypts an incoming UDP packet and reads a 4-byte big-endian timestamp embedded after the nonce. If the packet's timestamp is more than 60 seconds old, the request is considered stale (a replay or delayed datagram) and is rejected with "Expired request". This protects the packet protocol against replay attacks.

Source

Thrown at packetserverconn.go:71

		return nil, nil, err
	}

	cb, err := aes.NewCipher(ck)
	if err != nil {
		x.BP32.Put(ck)
		return nil, nil, err
	}
	x.BP32.Put(ck)
	ca, err := cipher.NewGCM(cb)
	if err != nil {
		return nil, nil, err
	}
	if _, err := ca.Open(b[:12], b[:12], b[12:], nil); err != nil {
		return nil, nil, err
	}
	i := int64(binary.BigEndian.Uint32(b[12 : 12+4]))
	if time.Now().Unix()-i > 60 {
		return nil, nil, errors.New("Expired request")
	}
	a, h, p, err := socks5.ParseBytesAddress(b[12+4:])
	if err != nil {
		return nil, nil, err
	}
	if 12+4+1+len(h)+2 >= len(b)-16 {
		return nil, nil, errors.New(fmt.Sprintf("invalid packet. length: %d address: %#x %#x %#x", len(b), a, h, p))
	}
	dst := socks5.ToAddress(a, h, p)
	f.Lock.Lock()
	c, ok := f.Conns[addr.String()+dst]
	f.Lock.Unlock()
	if ok {
		_ = c.In(b[12+4+1+len(h)+2 : len(b)-16])
		return nil, nil, nil
	}
	f.Lock.Lock()
	c = NewPacketConn(b[12+4+1+len(h)+2:len(b)-16], w, timeout, func() {

View on GitHub (pinned to 5cd13ef3b1)

Solutions

  1. Sync the client clock (NTP) so the embedded timestamp is within 60 seconds of the server clock.
  2. Regenerate/rebuild the client so each packet embeds time.Now().Unix() at send time instead of a stale value.
  3. Check for proxies/NAT buffering UDP datagrams for long periods; reduce queuing upstream.
  4. Verify client and server are in the same timezone-independent UTC epoch (they should be; investigate if timestamps differ systematically).

Example fix

// before: packet built with stale cached timestamp
ts := cachedTimestamp
// after: embed current time at send time
ts := uint32(time.Now().Unix())
Defensive patterns

Strategy: retry

Validate before calling

ts := time.Now().Unix()
// ensure client embeds ts at send time and clocks are NTP-synced
if math.Abs(float64(ts-serverTimeHint)) > 30 { go syncClockViaNTP() }

Try / catch

if strings.Contains(err.Error(), "Expired request") {
    // resend a fresh packet immediately after resyncing the clock
    time.Sleep(500 * time.Millisecond)
    return sendFreshPacket()
}

Prevention

When it happens

Trigger: Sending a UDP packet to the brook packet server whose embedded Unix timestamp (bytes 12..16 after decryption) is older than 60 seconds at processing time; system clock skew between client and server exceeding 60s; replaying captured packets.

Common situations: Client machine clock drifted behind server clock; queued/delayed UDP datagrams on a congested network; packet-capture replay tools; VMs with suspended clocks resuming and flushing old packets.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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