txthinking/brook · error
Expired request
Error message
Expired request
What it means
This error is thrown in the packet server's Handle function when the Unix timestamp embedded at bytes 32-36 of the incoming request packet is more than 60 seconds older than the server's current time. It is an anti-replay measure: clients must include a fresh timestamp so stale or replayed packets are rejected.
Source
Thrown at simplepacketserverconn.go:49
}
func NewSimplePacketServerConnFactory() *SimplePacketServerConnFactory {
return &SimplePacketServerConnFactory{
Conns: make(map[string]*PacketConn),
Lock: &sync.Mutex{},
}
}
func (f *SimplePacketServerConnFactory) Handle(addr *net.UDPAddr, b, p []byte, w func([]byte) (int, error), timeout int) (net.Conn, []byte, error) {
if len(b) < 32+4 {
return nil, nil, errors.New("data too small")
}
if bytes.Compare(p, b[:32]) != 0 {
return nil, nil, errors.New("Password is wrong")
}
i := int64(binary.BigEndian.Uint32(b[32 : 32+4]))
if time.Now().Unix()-i > 60 {
return nil, nil, errors.New("Expired request")
}
a, h, p, err := socks5.ParseBytesAddress(b[32+4:])
if err != nil {
return nil, nil, err
}
dst := socks5.ToAddress(a, h, p)
f.Lock.Lock()
c, ok := f.Conns[addr.String()+dst]
f.Lock.Unlock()
if ok {
_ = c.In(b[32+4+1+len(h)+2:])
return nil, nil, nil
}
f.Lock.Lock()
c = NewPacketConn(b[32+4+1+len(h)+2:], w, timeout, func() {
f.Lock.Lock()
delete(f.Conns, addr.String()+dst)
f.Lock.Unlock()View on GitHub (pinned to 5cd13ef3b1)
Solutions
- Sync the client's clock (enable NTP) so its Unix time matches the server within 60 seconds
- Ensure the client regenerates the timestamp for every request instead of reusing/caching packets
- Check for network paths (queued proxies, offline buffering) that delay packets more than 60s and reduce latency or retransmit promptly
- Verify the client writes the timestamp at offset 32 in BigEndian uint32, matching the server's read position
Example fix
// before (client caches/stale timestamp) i := cachedTimestamp binary.BigEndian.PutUint32(b[32:36], uint32(i)) // after i := time.Now().Unix() binary.BigEndian.PutUint32(b[32:36], uint32(i))
Defensive patterns
Strategy: validation
Validate before calling
ts := int64(binary.BigEndian.Uint32(req[32:36]))
if time.Now().Unix()-ts > 55 {
return errors.New("request would be rejected: timestamp older than 60s")
} Try / catch
dst, h, p, err := conn.Handle(req)
if err != nil && err.Error() == "Expired request" {
// resync clock and rebuild the request with a fresh timestamp
} Prevention
- Run NTP/chrony on all client hosts
- Generate a fresh timestamp per request, never cache packets
- Keep end-to-end latency under the 60s window
- Write the timestamp at offset 32 BigEndian to match the server
When it happens
Trigger: A UDP packet arrives whose embedded 4-byte BigEndian timestamp (b[32:36]) is older than 60 seconds, e.g. a replayed capture, a client with a skewed clock, or a packet delayed in transit beyond the 60s window.
Common situations: Client machine clock drifts behind the server by more than a minute; a proxy or queuing network delays datagrams; automated replay of captured packets; NTP disabled or misconfigured on the client.
Related errors
- Expired request
- socks5 server requires a clear IP for UDP, only port is not
- quic max datagram size is 1197
- when write to client, quic max datagram size is 1197
- no question
AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06).
Data as JSON: /api/errors/344905d071d738f5.
Report an issue: GitHub.