aboutsummaryrefslogtreecommitdiff
path: root/src/daemon
diff options
context:
space:
mode:
authorselsta <selsta@sent.at>2026-03-25 20:37:18 +0100
committerselsta <selsta@sent.at>2026-04-01 18:06:10 +0200
commit7f2cfe9294ec1fa7bece2a8069114c1b6985650f (patch)
tree06a5d19a645f700b02b9bdcacaff915c7bd9974a /src/daemon
parentdd0fb6c7552330a088033b0cfba0ba570bbbfd15 (diff)
downloadmonzero-core-7f2cfe9294ec1fa7bece2a8069114c1b6985650f.tar.gz
monzero-core-7f2cfe9294ec1fa7bece2a8069114c1b6985650f.tar.xz
monzero-core-7f2cfe9294ec1fa7bece2a8069114c1b6985650f.zip
zmq: add restricted rpc mode
Diffstat (limited to 'src/daemon')
-rw-r--r--src/daemon/command_line_args.h12
-rw-r--r--src/daemon/daemon.cpp51
-rw-r--r--src/daemon/main.cpp2
3 files changed, 60 insertions, 5 deletions
diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h
index 96fddc02d..a0b15d021 100644
--- a/src/daemon/command_line_args.h
+++ b/src/daemon/command_line_args.h
@@ -136,6 +136,18 @@ namespace daemon_args
, "Address for ZMQ pub - tcp://ip:port or ipc://path"
};
+ const command_line::arg_descriptor<bool> arg_restricted_zmq_rpc = {
+ "restricted-zmq-rpc"
+ , "Restrict ZMQ RPC to view-only / non-sensitive methods"
+ , false
+ };
+
+ const command_line::arg_descriptor<bool> arg_confirm_zmq_rpc_external_bind = {
+ "confirm-zmq-rpc-external-bind"
+ , "Confirm zmq-rpc-bind-ip value is NOT a loopback (local) IP"
+ , false
+ };
+
const command_line::arg_descriptor<bool> arg_zmq_rpc_disabled = {
"no-zmq"
, "Disable ZMQ RPC server"
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index 043e73501..e069d1b65 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -31,6 +31,7 @@
#include <memory>
#include <stdexcept>
#include <boost/algorithm/string/split.hpp>
+#include <boost/asio/ip/address.hpp>
#include "misc_log_ex.h"
#include "daemon/daemon.h"
#include "rpc/daemon_handler.h"
@@ -58,10 +59,39 @@ using namespace epee;
namespace daemonize {
+namespace
+{
+ void verify_zmq_rpc_bind(const boost::program_options::variables_map& vm)
+ {
+ std::string bind_ip = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_ip);
+ if (bind_ip.empty())
+ return;
+
+ // ZMQ bind input already accepts bracketed IPv6 literals, but
+ // boost::asio::ip::make_address does not.
+ if (bind_ip.size() >= 2 && bind_ip.front() == '[' && bind_ip.back() == ']')
+ bind_ip = bind_ip.substr(1, bind_ip.size() - 2);
+
+ boost::system::error_code ec{};
+ const auto parsed_ip = boost::asio::ip::make_address(bind_ip, ec);
+ if (ec)
+ throw std::runtime_error{"Invalid IP address given for --" + std::string(daemon_args::arg_zmq_rpc_bind_ip.name)};
+
+ if (!parsed_ip.is_loopback() && !command_line::get_arg(vm, daemon_args::arg_confirm_zmq_rpc_external_bind))
+ {
+ throw std::runtime_error{
+ std::string{"--"} + daemon_args::arg_zmq_rpc_bind_ip.name +
+ " permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --" +
+ daemon_args::arg_confirm_zmq_rpc_external_bind.name
+ };
+ }
+ }
+}
+
struct zmq_internals
{
- explicit zmq_internals(t_core& core, t_p2p& p2p)
- : rpc_handler{core.get(), p2p.get()}
+ explicit zmq_internals(t_core& core, t_p2p& p2p, const bool restricted)
+ : rpc_handler{core.get(), p2p.get(), restricted}
, server{rpc_handler}
{}
@@ -104,7 +134,10 @@ public:
if (!command_line::get_arg(vm, daemon_args::arg_zmq_rpc_disabled))
{
- zmq.reset(new zmq_internals{core, p2p});
+ verify_zmq_rpc_bind(vm);
+
+ const bool restricted = command_line::get_arg(vm, daemon_args::arg_restricted_zmq_rpc);
+ zmq.reset(new zmq_internals{core, p2p, restricted});
const std::string zmq_port = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_port);
const std::string zmq_address = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_ip);
@@ -133,12 +166,20 @@ public:
{
MWARNING("WARN: --zmq-rpc-bind-port has no effect because --no-zmq was specified");
}
- else if (command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_ip) !=
+ if (command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_ip) !=
daemon_args::arg_zmq_rpc_bind_ip.default_value)
{
MWARNING("WARN: --zmq-rpc-bind-ip has no effect because --no-zmq was specified");
}
- else if (!command_line::get_arg(vm, daemon_args::arg_zmq_pub).empty())
+ if (command_line::get_arg(vm, daemon_args::arg_confirm_zmq_rpc_external_bind))
+ {
+ MWARNING("WARN: --confirm-zmq-rpc-external-bind has no effect because --no-zmq was specified");
+ }
+ if (command_line::get_arg(vm, daemon_args::arg_restricted_zmq_rpc))
+ {
+ MWARNING("WARN: --restricted-zmq-rpc has no effect because --no-zmq was specified");
+ }
+ if (!command_line::get_arg(vm, daemon_args::arg_zmq_pub).empty())
{
MWARNING("WARN: --zmq-pub has no effect because --no-zmq was specified");
}
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 38b99ff49..39ef04772 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -158,6 +158,8 @@ int main(int argc, char const * argv[])
command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_ip);
command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_port);
command_line::add_arg(core_settings, daemon_args::arg_zmq_pub);
+ command_line::add_arg(core_settings, daemon_args::arg_confirm_zmq_rpc_external_bind);
+ command_line::add_arg(core_settings, daemon_args::arg_restricted_zmq_rpc);
command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_disabled);
daemonizer::init_options(hidden_options, visible_options);