Commit Graph

31 Commits

Author SHA1 Message Date
merge-script
5f0daa0eae Merge bitcoin/bitcoin#36169: http: Use SO_EXCLUSIVEADDRUSE on Windows
bcb09b3f4a qa: Verify HTTP listen port exclusivity (Hodlinator)
af65069fd1 windows: Use SO_EXCLUSIVEADDRUSE over SO_REUSEADDR (Hodlinator)

Pull request description:

  #### Problem

  `HTTPServer::BindAndStartListening()` unconditionally enables `SO_REUSEADDR` before binding the RPC listener. On Windows, a reuse-enabled listener does not reserve the port exclusively: another local process can request `SO_REUSEADDR` and bind to the same port (see https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse).

  If the competing socket receives a new connection, it can capture the HTTP Basic `Authorization` header (including the cookie credential) and proxy or issue privileged RPC calls as the victim. This crosses a local-user boundary and can expose wallet-controlling RPC credentials.

  #### Fix

  Have Windows use `SO_EXCLUSIVEADDRUSE` instead which makes the port exclusive to the process which first requests it, while retaining the restart-friendly behavior which `SO_REUSEADDR` enabled. Abort if another process is already bound to the port.

  #### Further context & rationale

  This issue is new in our homegrown HTTP server implementation, since libevent had a guard against setting `SO_REUSEADDR` on Windows, see `evutil_make_listen_socket_reuseable()` d82464a277/evutil.c (L483). libevent does not reference `SO_EXCLUSIVEADDRUSE`.

  Why should we not just avoid `SO_REUSEADDR` on Windows and skip `SO_EXCLUSIVEADDRUSE` like the libevent approach?
  Because setting either option makes the process less prone to failing to bind to a port after having been restarted. Not sure why this wasn't an issue before, maybe the node startup was usually slow enough to time out the port before we tried to re-bind it on Windows.

  ---

  Discovered by Project Loupe.

ACKs for top commit:
  pinheadmz:
    ACK bcb09b3f4a
  sedited:
    utACK bcb09b3f4a
  jeanpablojp:
    tACK bcb09b3f4a

Tree-SHA512: 7f2362cc8399e8c4e95b27b39066d3e591b5aebfc2b562aba10786609456f526f562394818a3d1042d64dabf497548ffabf0757322cfb201454a134321108cf5
2026-09-06 10:35:43 +02:00
merge-script
f0c839ace5 Merge bitcoin/bitcoin#36123: http: throttle per-connection reads while a request is in flight
3d1004cb9b http: throttle per-connection reads while a request is in flight (Matthew Zipkin)

Pull request description:

  This patches a memory exhaustion scenario found while auditing the new http server with kimi-k3. A shallow version of this scenario was addressed in #35735 (See  https://github.com/bitcoin/bitcoin/pull/35735#discussion_r3720177656 and https://github.com/bitcoin/bitcoin/pull/35735#issuecomment-5217000202) but a OOM vector still remained.

  On master when the sever is busy handling a request from a client, it will still read data from that client and "queue up" the next request. In #35735 we handled the scenario where that additional incoming data was an invalid HTTP request by not attempting to parse the data. However, we didn't add a size limit.

  A misbehaving client could block its request queue with something like `waitforblock` and then flood the server with nonsense data without any limit.

  The solution in this patch is to not even read from the socket at all if we are busy with a request. Similar to the intent of #35735, the kernel will buffer incoming data until backpressure kicks in and the TCP window drops to 0.

  If unaddressed, the attack vector is still limited to authenticated clients: unauthenticated REST requests don't block for very long, so the server *should* be able to drain the receive buffer.

ACKs for top commit:
  jeanpablojp:
    tACK 3d1004cb9b
  frankomosh:
    ACK 3d1004cb9b
  hodlinator:
    ACK 3d1004cb9b
  winterrdog:
    tACK 3d1004cb9b
  sedited:
    ACK 3d1004cb9b

Tree-SHA512: 56f7678a9ab6789aa542c1f252df0b6ccf9137cb426ff915a0a3fe8285200fdb62b7a47c476ed8617c3592e7a7eac18158cd8c0dac309cdcf4e5fd887e016209
2026-09-05 17:15:57 +02:00
Hodlinator
bcb09b3f4a qa: Verify HTTP listen port exclusivity 2026-09-04 22:05:31 +02:00
Matthew Zipkin
a51df9b0ec test: tolerate race condition in interface_http.py
Fixes #35632 by allowing both outcomes of a race condition.
The server behavior is unchanged: in response to a malformed request
we send an error code and disconnect. The issue is that sometimes
on Windows the RST is caught by the platform and the receive buffer
is discarded before the Python client can process it with recv().

We can also be much more polite to misbehaving clients by
implementing SO_LINGER as suggested in #35780 but that will require
more review.
2026-09-02 13:42:57 -04:00
Matthew Zipkin
3d1004cb9b http: throttle per-connection reads while a request is in flight
A client streaming pipelined requests into a busy connection
(or any connection whose replies are slower than the sender) could grow
server memory without limit, up to remote OOM.

Stop selecting RecvEvent for clients whose request is being processed;
pipelined data then backs up in the kernel socket buffer, applying TCP
backpressure to the sender. One request per connection is in flight
at a time.

Functional test streams pipelined submitblock requests into a connection
blocked on waitforblockheight. Unpatched builds continue draining the
socket buffer indefinitely, patched builds will stall.
2026-09-01 15:56:09 -04:00
Hennadii Stepanov
b8a8893bf2 qa: Lower -rpcmaxconnections in interface_http.py test
On some systems, such as NetBSD, the non-default
`-rpcmaxconnections=128` is too high, so bitcoind refuses to start:
```
Error: Not enough file descriptors available. 256 available, 290 required.
```

The test only needs a value above the default of 16. Use 64 and lower
`-maxconnections` in that case so the total fits in 256.
2026-08-25 16:54:59 +01:00
Hodlinator
7e3b60584b refactor(qa): Simplify through using assert_raises() 2026-08-24 13:21:39 +02:00
Matthew Zipkin
cc2acebefb http: configure simultaneous connection limit with -rpcmaxconnections 2026-08-17 08:07:46 -04:00
Matthew Zipkin
b3d6d2d1a7 http: limit connected clients to 16 2026-08-17 07:35:47 -04:00
Matthew Zipkin
9954aa7728 http: don't parse any new requests from a client if m_req_busy = true 2026-08-10 10:52:42 -04:00
Matthew Zipkin
90676e24ad Add state to HTTPRequest to avoid duplicate work over I/O cycles 2026-08-10 10:52:37 -04:00
Matthew Zipkin
d1ed2a6e25 http: check rpcallowip immediately after accepting connection
Instead of sending 403 Forbidden, disconnect as soon as possible.

To facilitate unit testing, this commit includes a refactor
that moves the subnet allow list and relevant methods
into the HTTPServer class instead of file-scope static scope.
2026-07-08 11:29:26 -04:00
Matthew Zipkin
21c7542cf8 http: switch servers from libevent to bitcoin 2026-06-22 05:47:00 -04:00
Matthew Zipkin
881d4b6c75 test: cover common HTTP attacks and common malformed requests 2026-06-22 05:46:31 -04:00
MarcoFalke
fa24693819 test: Allow --usecli in tests that already support it 2026-05-26 07:47:35 +02:00
Matthew Zipkin
f49a2afd94 test: interface_http follow-ups
- Only one node needed for test
- Use ascii encoding instead of utf-8
- Make tests independent of each other
- Expect HTTP error code 413 for too-large request
- Clarify python client race condition in comment
2026-04-17 10:45:03 -04:00
Matthew Zipkin
422ca211ec test: ensure HTTP server enforces limits on headers and body size 2026-04-07 10:45:45 -04:00
Matthew Zipkin
0c1a07e890 test: ensure HTTP server timeout is not caused by a delayed response 2026-04-06 15:35:25 -04:00
Matthew Zipkin
f06de5c1ea test: clean up and modernize interface_http 2026-04-06 15:35:15 -04:00
MarcoFalke
fa5f297748 scripted-diff: [doc] Unify stale copyright headers
-BEGIN VERIFY SCRIPT-

 sed --in-place --regexp-extended \
   's;( 20[0-2][0-9])(-20[0-2][0-9])? The Bitcoin Core developers;\1-present The Bitcoin Core developers;g' \
   $( git grep -l 'The Bitcoin Core developers' -- ':(exclude)COPYING' ':(exclude)src/ipc/libmultiprocess' ':(exclude)src/minisketch' )

-END VERIFY SCRIPT-
2025-12-16 22:21:15 +01:00
Matthew Zipkin
f16c8c67bf tests: Expand HTTP coverage to assert libevent behavior
Covers:
- http pipelining
- rpcservertimeout

  Testing this requires adding an option to TestNode to force
  the test framework to establish a new HTTP connection for
  every RPC. Otherwise, attempting to reuse a persistent connection
  would cause framework RPCs during startup and shutdown to fail.

- "chunked" Transfer-Encoding
2025-05-21 10:47:23 -04:00
Hennadii Stepanov
a0473442d1 scripted-diff: Add __file__ argument to BitcoinTestFramework.init()
-BEGIN VERIFY SCRIPT-
sed -i -e 's/\s*().main\s*()/(__file__).main()/' $(git ls-files test/functional/*.py)
sed -i -e 's/def __init__(self)/def __init__(self, test_file)/' test/functional/test_framework/test_framework.py
-END VERIFY SCRIPT-
2024-07-16 22:06:47 +01:00
MarcoFalke
fac23c2114 scripted-diff: Bump copyright headers
The previous diff touched most files in ./test/, so bump the headers to
avoid having to touch them again for a bump later.

-BEGIN VERIFY SCRIPT-
./contrib/devtools/copyright_header.py update ./test/
-END VERIFY SCRIPT-
2021-11-10 11:10:24 +01:00
fanquake
c2a5d560df test: use f-strings in interface_*.py tests 2021-08-18 12:39:20 +08:00
practicalswift
993e38a4e2 tests: Mark functional tests not supporting bitcoin-cli (--usecli) as such 2019-12-06 14:40:28 +00:00
MarcoFalke
faa7cdf764 scripted-diff: Update copyright in ./test
-BEGIN VERIFY SCRIPT-
./contrib/devtools/copyright_header.py update ./test/
-END VERIFY SCRIPT-
2019-03-02 10:58:35 -05:00
MarcoFalke
fa0e65b772 scripted-diff: test: Remove brackets after assert
-BEGIN VERIFY SCRIPT-
sed -i --regexp-extended -e 's/assert ?\((.+)\)(( )*)?(#.*)?$/assert \1\3\3\4/g' $(git grep -l --extended-regexp 'assert ?\(' test)
-END VERIFY SCRIPT-
2019-03-02 10:51:35 -05:00
Daniel Ingram
17b55202da Compare to None with is/is not 2018-12-10 15:11:37 -05:00
practicalswift
68400d8b96 tests: Use explicit imports 2018-08-13 14:13:39 +02:00
DrahtBot
eb7daf4d60 Update copyright headers to 2018 2018-07-27 07:15:02 -04:00
Anthony Towns
3150b3fea7 [tests] Rename misc functional tests. 2018-01-25 09:44:30 +10:00