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
- Sync the client clock (NTP) so the embedded timestamp is within 60 seconds of the server clock.
- Regenerate/rebuild the client so each packet embeds time.Now().Unix() at send time instead of a stale value.
- Check for proxies/NAT buffering UDP datagrams for long periods; reduce queuing upstream.
- 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
- Run NTP/chrony on all hosts running brook clients or servers.
- Never cache the timestamp used to build packets; always call time.Now() per packet.
- Avoid long-lived UDP send queues; drop datagrams older than ~30s client-side.
- Monitor clock skew between client and server hosts.
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
- Expired request
- Expired request
- Expired request
- socks5 server requires a clear IP for UDP, only port is not
- socks5 server requires a clear IP for UDP, only port is not
AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06).
Data as JSON: /api/errors/77a24f0b505488a1.
Report an issue: GitHub.