fix(cuprate): stop publishing the unauthenticated unrestricted RPC
The manifest bound cuprated's unrestricted RPC (full node control) to 0.0.0.0 inside the container with i_know_what_im_doing_allow_public_unrestricted_rpc = true, relying on ports[].bind: 127.0.0.1 to keep it private. That only restricts the HOST side. Verified live on archi-dev-box 2026-08-22: a peer container got a valid unauthenticated get_info off container port 18081 — and still did after cuprate was moved to its own network, because podman bridges route to each other unless created with --opt isolate=true, which the orchestrator's auto-create does not pass. Every app on the node could therefore drive full node control with no credential. The PR justified this as the pattern bitcoin-knots already uses, but knots writes rpcuser/rpcpassword from generated secrets, so a 0.0.0.0 bind there still is not control without credentials. cuprated has no RPC authentication at all, so the two are not equivalent. Unrestricted RPC is now left at cuprated's own default — container loopback only, published nowhere, reachable by nothing — which is what upstream intends by refusing a non-local bind without an explicit override. Restricted RPC (the safe-for-public subset wallets use) and p2p are unchanged, and health_check moves to 18089 since 18184 is gone. Re-verified after the change: peer container gets connection refused on 18081 (exit 7), restricted RPC and the health endpoint still answer, the node still syncs, validator APPROVED, 76/76 container tests pass including the unauthenticated-port canary (still 28 — an auth: local port was removed, not an auth: none one). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d6b48ce095
commit
f1b5d2d267
+14
-16
@@ -67,17 +67,18 @@ app:
|
|||||||
auth: none
|
auth: none
|
||||||
auth_rationale: >-
|
auth_rationale: >-
|
||||||
Monero p2p gossip. Peers are anonymous by design and speak the Monero wire protocol, not HTTP.
|
Monero p2p gossip. Peers are anonymous by design and speak the Monero wire protocol, not HTTP.
|
||||||
# Unrestricted RPC: full node control (mining, wallet-adjacent calls).
|
# Unrestricted RPC (full node control) is deliberately NOT published.
|
||||||
# cuprated enables this by default bound to 127.0.0.1 and refuses to
|
# cuprated has no RPC authentication, and for a published port to reach
|
||||||
# start if pointed at a non-local address without an explicit opt-in
|
# it the service would have to bind 0.0.0.0 inside the container — at
|
||||||
# flag — this mirrors that intent at the gate too. Host port differs
|
# which point every other app can reach it directly on 18081, since
|
||||||
# from Monero's canonical 18081 for the same reason as P2P above
|
# ports[].bind only restricts the HOST side and podman bridges route to
|
||||||
# (nostr-rs-relay already holds 18081 on this fleet).
|
# each other (verified live 2026-08-22: a peer container on archy-net
|
||||||
- host: 18184
|
# got an unauthenticated get_info, from a *different* network). That is
|
||||||
container: 18081
|
# unlike bitcoin-knots, whose 0.0.0.0 RPC still demands the rpcuser /
|
||||||
protocol: tcp
|
# rpcpassword it writes from generated secrets. So unrestricted RPC is
|
||||||
bind: 127.0.0.1
|
# left at cuprated's own default — container loopback only, reachable by
|
||||||
auth: local
|
# nothing — which is also what upstream intends by refusing a non-local
|
||||||
|
# bind without an explicit i_know_what_im_doing override.
|
||||||
# Restricted RPC: Monero's own purpose-built safe-for-public subset —
|
# Restricted RPC: Monero's own purpose-built safe-for-public subset —
|
||||||
# what wallets use when connecting to a "remote node". Disabled by
|
# what wallets use when connecting to a "remote node". Disabled by
|
||||||
# cuprated's own default; enabled via files[] below. A dashboard login
|
# cuprated's own default; enabled via files[] below. A dashboard login
|
||||||
@@ -128,17 +129,14 @@ app:
|
|||||||
network = "Mainnet"
|
network = "Mainnet"
|
||||||
target_max_memory = 3000000000
|
target_max_memory = 3000000000
|
||||||
|
|
||||||
[rpc.unrestricted]
|
|
||||||
address = "0.0.0.0"
|
|
||||||
i_know_what_im_doing_allow_public_unrestricted_rpc = true
|
|
||||||
|
|
||||||
[rpc.restricted]
|
[rpc.restricted]
|
||||||
enable = true
|
enable = true
|
||||||
overwrite: false
|
overwrite: false
|
||||||
|
|
||||||
health_check:
|
health_check:
|
||||||
type: tcp
|
type: tcp
|
||||||
endpoint: localhost:18184
|
# Restricted RPC — the only RPC surface published now.
|
||||||
|
endpoint: localhost:18089
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|||||||
Reference in New Issue
Block a user