#36204 http: disconnect clients that never finish a request
https://github.com/bitcoin/bitcoin/pull/36204 · · +250/-12 in 4 files, 2 commits · labels: RPC/REST/ZMQ
Goal
- Prevent slow-trickling HTTP clients from tying up RPC connection slots indefinitely
- Protects RPC and REST callers from denial-of-service slot exhaustion
This pull request introduces an HTTP request completion deadline to prevent clients from monopolizing connection slots indefinitely. Previously, -rpcservertimeout only checked for socket inactivity, allowing a client to keep a slot occupied by trickling request bytes slowly enough to avoid the idle timeout. The fix arms a non-resettable deadline upon receiving the first byte of a request, terminating connections that fail to finish sending their request within the timeout window.
Problem: Because -rpcservertimeout resets whenever bytes are read, an unauthenticated client trickling data can consume an RPC connection slot forever without ever finishing an HTTP request. With connection slots capped by -rpcmaxconnections (default 16), a handful of trickling sockets can exhaust all available slots and block all subsequent RPC calls.
Category: RPC / REST / ZMQ (#3 of 52)
P2 · DoS protection
- P2 because it prevents denial-of-service exhaustion of limited RPC connection slots
- Protects node RPC availability even though exposure is typically limited to localhost
Prevents HTTP connection slot exhaustion through slowloris-style trickled requests. While RPC typically listens on localhost by default, unauthenticated local or network clients can starve all connection slots without reaching authentication.
Membership: Modifies src/httpserver.cpp and src/httpserver.h to manage client timeouts and connection lifecycles.
Factors: security/stability 2, bug 1, performance 0, user value 1, leverage 0
Reviewability: Ready
- Ready to review
- Clean state with feedback from the initial review round addressed
The code is clean, CI passes, and the author addressed reviewer feedback in recent updates.
Author status: active
Resolved concerns:
Agreement: Positive
- Positive sentiment with initial review feedback addressed
- Concept approval and detailed technical review on timeouts and tests (hodlinator)
Positive, with Concept ACK and review suggestions addressed (hodlinator)
The change received a Concept ACK from hodlinator with several suggestions on tests and timeout handling, all of which were addressed or answered by the author.
- 2026-09-11 hodlinator: "Concept ACK 537944cb7869039912139793b58bc6296b64eebe"
- 2026-09-14 janb84: addressed review feedback and updated tests
Objections:
| Reviewer | Kind | Harm | Status | Blocking | Author replied | Quote |
|---|---|---|---|---|---|---|
| hodlinator | approach | Suboptimal condition check ordering could cause minor unnecessary evaluation overhead | resolved | no | yes | 2026-09-11: "nanonit: Feels like !m_req_busy would be the cheapest check and be the first one (same for is_idle)." Settled: 2026-09-14: "Have to pushback on this one, m_req_busy is mostly false so the negate makes that true. It would cause an extra check that is mostly true and therefor does not short the evaluation." |
Support:
- hodlinator: Concept ACK 537944cb7869039912139793b58bc6296b64eebe [not substantive]
Participants: hodlinator (support)
State derived from the lists: support without stated reasons, no open objection (hodlinator)
Review verdicts (DrahtBot): 0
- Concept ACK: hodlinator
Files
193 lines under test/bench/ci.
- src/test/httpserver_tests.cpp +120/-10
- test/functional/interface_http.py +63/-0
- src/httpserver.cpp +42/-2
- src/httpserver.h +25/-0
Card
Adds a completion deadline for incoming HTTP requests so clients cannot monopolize connection slots by trickling data indefinitely. Currently, the idle timeout resets on every received byte, allowing an attacker or slow client to exhaust -rpcmaxconnections without ever sending a full request or reaching authentication. Reviewer hodlinator provided a Concept ACK and detailed review comments that the author addressed. The PR is ready for review with unit and functional test coverage.