Skip to content

Bound HTTP connections and slow request lifetime #107

Description

@tnull

Summary

The HTTP accept loop spawns one Tokio task for every accepted TCP connection
and serves it with Hyper HTTP/1 without a global/per-IP concurrency limit or
explicit header-read/idle timeout.

Authentication is reached only after a complete request, so unauthenticated
clients can retain tasks and file descriptors with incomplete slow requests.

Observed on 88a5703496386465556d920dccf49512296c53d0 (current main).

Impact

A remote client can cause task/file-descriptor exhaustion and prevent
legitimate clients from connecting. A correctly configured reverse proxy may
mitigate this, but the shipped server and Compose setup do not enforce one.

Code evidence

server/src/main.rs:160-177 accepts each connection and immediately calls
runtime.spawn, with no semaphore or timeout around
http1::Builder::new().serve_connection(...).

Proof of concept

Against a disposable local instance, a slow-header test can be run with:

slowhttptest -H -c 1000 -r 100 -i 10 -s 8192 -u http://127.0.0.1:8080/vss/getObject

During the run, observe the server's open file descriptors/tasks grow while
the clients leave HTTP headers incomplete.

Suggested remediation

  • Bound concurrent connections with a semaphore and return capacity promptly.
  • Configure header-read and idle timeouts with a Hyper timer.
  • Consider per-source limits and document required proxy limits.

Reported by Bitcoin Red Team.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions