http: drop connections from RPC clients that are not allowed to connect #35772

pull janb84 wants to merge 2 commits into bitcoin:master from janb84:disconnect_client_server_side changing 2 files +64 −2
  1. janb84 commented at 12:13 PM on July 22, 2026: contributor

    This PR changes the way how a ClientAllowed rejection is handled.

    Currently whether to drop the connection to a refused client is the client's choice instead of the server. A client whose address is not covered by -rpcallowip gets a 403 Forbidden, but the connection is not actively closed. This PR changes that by setting a Connection close header on reject and a change in the WriteReply() function makes that now the connection is closed based on a close requested by either side. The client is disconnected once the reply has been flushed.

    So a rejected client asking for keep-alive (the HTTP/1.1 default) does not hold a slot until -rpcservertimeout expires anymore. Whether to drop a refused connection should not be that peer's choice. This fixes a DDOS vector that will increase severity if #35730 is merged (due to the limited number of connections)

    How to reproduce:

    <details>

    Start a bitcoin node with -rpcallowip=1.1.1.1 -rpcbind=<ip> -rpcservertimeout=30 -debug=http eg:

     ./build/bin/bitcoind --regtest -rpcallowip=1.1.1.1 -rpcbind=10.0.6.30 -rpcservertimeout=30 -debug=http
    

    Run a timed netcat connection:

    time { printf 'POST / HTTP/1.1\r\nHost: <ip>:18443\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n'; sleep 35; } | nc <ip> 18443
    

    On master:

    nc output:

    HTTP/1.1 403 Forbidden
    Date: Wed, 22 Jul 2026 11:45:51 GMT
    Content-Length: 0
    Content-Type: text/html; charset=ISO-8859-1
    
    
    real    0m35.026s
    user    0m0.009s
    sys     0m0.012s
    

    bitcoind log:

    2026-07-22T11:45:51Z [http] HTTP Connection accepted from 10.0.6.30:56618 (id=1)
    2026-07-22T11:45:51Z [http] Received a POST request for / from 10.0.6.30:56618 (id=1)
    2026-07-22T11:45:51Z [http] HTTP request from 10.0.6.30:56618 rejected: Client network is not allowed RPC access
    2026-07-22T11:45:51Z [http] HTTPResponse (status code: 403 size: 127) added to send buffer for client 10.0.6.30:56618 (id=1)
    2026-07-22T11:45:51Z [http] Sent 127 bytes to client 10.0.6.30:56618 (id=1)
    2026-07-22T11:46:21Z [http] HTTP client idle timeout 10.0.6.30:56618 (id=1)
    2026-07-22T11:46:21Z [http] Disconnecting HTTP client 10.0.6.30:56618 (id=1)
    

    This PR:

    nc output:

    HTTP/1.1 403 Forbidden
    Date: Wed, 22 Jul 2026 11:48:09 GMT
    Content-Length: 0
    Content-Type: text/html; charset=ISO-8859-1
    Connection: close
    
    
    real    0m35.020s
    user    0m0.012s
    sys     0m0.011s
    

    bitcoind log:

    2026-07-22T11:48:09Z [http] HTTP Connection accepted from 10.0.6.30:56626 (id=0)
    2026-07-22T11:48:09Z [http] Received a POST request for / from 10.0.6.30:56626 (id=0)
    2026-07-22T11:48:09Z [http] HTTP request from 10.0.6.30:56626 rejected: Client network is not allowed RPC access
    2026-07-22T11:48:09Z [http] HTTPResponse (status code: 403 size: 146) added to send buffer for client 10.0.6.30:56626 (id=0)
    2026-07-22T11:48:09Z [http] Sent 146 bytes to client 10.0.6.30:56626 (id=0)
    2026-07-22T11:48:09Z [http] Disconnecting HTTP client 10.0.6.30:56626 (id=0)
    

    </details>

  2. test: check the server disconnects a rejected RPC client
    A client whose address is not in -rpcallowip gets a 403, but a client
    asking for "Connection: keep-alive" must not be able to hold the
    connection open.
    6d75ebd064
  3. http: disconnect rejected RPC clients immediately instead of allowing open connections 72757520d5
  4. DrahtBot added the label RPC/REST/ZMQ on Jul 22, 2026
  5. DrahtBot commented at 12:13 PM on July 22, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35772.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process. A summary of reviews will appear here.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35780 (http: linger-close after parse errors so clients can read the reply by b-l-u-e)
    • #35592 (http: check rpcallowip immediately after accepting connection by pinheadmz)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  6. pinheadmz commented at 12:25 PM on July 22, 2026: member

    Haven't reviewed this yet but is the issue already covered by #35592 ?

  7. janb84 marked this as a draft on Jul 22, 2026
  8. janb84 commented at 12:34 PM on July 22, 2026: contributor

    Haven't reviewed this yet but is the issue already covered by #35592 ?

    ugh! yes but partially, let me re-work it. Thanks

  9. DrahtBot added the label CI failed on Jul 22, 2026
  10. janb84 commented at 1:35 PM on July 23, 2026: contributor

    The reworked code comes down to only the change in the WriteReply() function. The change would only be used for the (now) ignored line 185 of httpserver.cpp (sends headers without a connection close).

    I do not think this is currently worthy to PR, or overkill for one line of code. So closing this instead.

  11. janb84 closed this on Jul 23, 2026


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-07-25 06:50 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me