Skip to content

relay: WS upgrade handshake timeout — cap upgrade time to bound slow-loris exposure #35

@ilmoniemi

Description

@ilmoniemi

User Story

As the relay operator, I want connections that stall during the WebSocket upgrade to be dropped within roughly 5 seconds, so that a slow-loris peer cannot pin sockets and goroutines on an internet-exposed surface indefinitely.

Context

http.Server's ReadTimeout/WriteTimeout (set in #9) govern the HTTP request lifecycle but stop applying once the connection is hijacked inside websocket.Accept. Today the three http.Server instances in cmd/pyrycode-relay/main.go set ReadHeaderTimeout: 10 * time.Second; that is the only bound on a peer that opens TCP and then dribbles the WS-upgrade request headers byte-by-byte. The relay is internet-exposed and assumes adversarial input by default (see docs/threat-model.md). Per-frame deadlines (#15) and the heartbeat ping/pong (#7) already cover slow peers after the upgrade succeeds; this ticket targets the pre-upgrade window only.

Acceptance Criteria

  • A peer that holds the TCP connection open without completing the WebSocket upgrade handshake within ~5 seconds has its connection closed by the relay.
  • The bound applies on both /v1/server and /v1/client.
  • The bound applies in both --insecure-listen and --domain (autocert) modes — i.e. across all http.Server instances configured in cmd/pyrycode-relay/main.go.
  • A test in the internal/relay package simulates a slow upgrade (e.g. a net.Conn that writes upgrade-request bytes with deliberate pauses, or never completes) and asserts the relay closes the connection on or before the configured deadline.
  • The 5s deadline is a literal at the wiring site, not buried in handler internals (consistent with the established "policy values live at the wiring site" pattern in docs/PROJECT-MEMORY.md).
  • make vet, make test (-race), and make build remain clean.

Technical Notes

Size Estimate

XS — small set of timeout literals at the wiring site plus a focused slow-handshake test.

Metadata

Metadata

Assignees

No one assigned

    Labels

    security-sensitiveTouches auth, crypto, or internet-exposed input pathssize:xsTiny ticket: <30 lines production code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions