txthinking/brook · error
Expired request
Error message
Expired request
What it means
NewSimpleStreamServer reads a 4-byte BigEndian Unix timestamp at the start of the payload (b[:4]) and rejects the request if it is more than 60 seconds in the past, returning 'Expired request'. This prevents replay of captured handshakes.
Source
Thrown at simplestreamserver.go:69
if bytes.Compare(password, b[:32]) != 0 {
x.BP2048.Put(b)
WaitReadErr(s.Client)
return nil, errors.New("Password is wrong")
}
l := int(binary.BigEndian.Uint16(b[32:34]))
if l > 2048 {
x.BP2048.Put(b)
return nil, errors.New("data too long")
}
if _, err := io.ReadFull(s.Client, b[:l]); err != nil {
x.BP2048.Put(b)
return nil, err
}
i := int64(binary.BigEndian.Uint32(b[:4]))
if time.Now().Unix()-i > 60 {
x.BP2048.Put(b)
WaitReadErr(s.Client)
return nil, errors.New("Expired request")
}
if i%2 == 0 {
s.network = "tcp"
s.RB = b
s.WB = x.BP2048.Get().([]byte)
}
if i%2 == 1 {
s.network = "udp"
s.Timeout = udptimeout
s.RB = x.BP65507.Get().([]byte)
copy(s.RB[:l], b[:l])
x.BP2048.Put(b)
s.WB = x.BP65507.Get().([]byte)
}
s.dst = socks5.ToAddress(s.RB[4], s.RB[4+1:l-2], s.RB[l-2:])
return ServerGate(s)
}
View on GitHub (pinned to 5cd13ef3b1)
Solutions
- Enable NTP on the client so clocks agree within 60 seconds
- Regenerate the timestamp (time.Now().Unix()) for every handshake, honoring the tcp odd/even parity scheme
- Do not reuse cached handshake buffers containing old timestamps on reconnect
- Investigate and eliminate network delays exceeding 60s (offline queuing, buffering proxies)
Example fix
// before (client reuses old handshake buffer) conn.Write(cachedHandshake) // after i := time.Now().Unix() binary.BigEndian.PutUint32(b[36:40], uint32(i)) conn.Write(b[:36+4+len(dst)])
Defensive patterns
Strategy: validation
Validate before calling
i := time.Now().Unix()
if binary.BigEndian.Uint32(handshake[36:40]) != uint32(i) || time.Now().Unix()-int64(i) > 55 {
return errors.New("handshake timestamp stale; rebuild before sending")
} Try / catch
s, err := NewSimpleStreamServer(password, conn, ...)
if err != nil && err.Error() == "Expired request" {
log.Printf("expired handshake from %s (clock skew or replay?)", conn.RemoteAddr())
conn.Close()
} Prevention
- Run NTP on every client host
- Build the handshake immediately before sending; never reuse buffers
- Account for the tcp odd/even timestamp parity when constructing the timestamp
- Alert on spikes of expired handshakes — they indicate clock drift or replay attempts
When it happens
Trigger: The timestamp decoded from b[:4] satisfies time.Now().Unix()-i > 60 — replayed handshake capture, client clock more than a minute behind the server, or delayed delivery of the request.
Common situations: Clock skew between client and server (NTP off, VM suspended); resending a recorded handshake (replay attack); long-lived queued/proxied connections exceeding the 60s window; client caching the timestamp across reconnects.
Related errors
AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06).
Data as JSON: /api/errors/3390a7ba9cf6ec59.
Report an issue: GitHub.