From 13ff355cf6081776fd7379080c17246e35c1236d Mon Sep 17 00:00:00 2001 From: Lee *!* Clagett Date: Tue, 21 Jan 2025 09:56:52 -0500 Subject: Set response limits on http server connections --- src/cryptonote_config.h | 4 ++++ src/p2p/net_node.cpp | 2 +- src/rpc/core_rpc_server.cpp | 47 +++++++++++++++++++++++++++++++++++++++- src/rpc/core_rpc_server.h | 5 ++++- src/wallet/wallet_rpc_server.cpp | 27 ++++++++++++++++++++++- 5 files changed, 81 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index d69556acd..82891b9de 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -127,6 +127,10 @@ #define COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT 1000 #define COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT 20000 +#define DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP 3 +#define DEFAULT_RPC_MAX_CONNECTIONS_PER_PRIVATE_IP 25 +#define DEFAULT_RPC_MAX_CONNECTIONS 100 +#define DEFAULT_RPC_SOFT_LIMIT_SIZE 25 * 1024 * 1024 // 25 MiB #define MAX_RPC_CONTENT_LENGTH 1048576 // 1 MB #define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000 diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index f9803fd81..2085b38ee 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -169,7 +169,7 @@ namespace nodetool const command_line::arg_descriptor arg_pad_transactions = { "pad-transactions", "Pad relayed transactions to help defend against traffic volume analysis", false }; - const command_line::arg_descriptor arg_max_connections_per_ip = {"max-connections-per-ip", "Maximum number of connections allowed from the same IP address", 1}; + const command_line::arg_descriptor arg_max_connections_per_ip = {"max-connections-per-ip", "Maximum number of p2p connections allowed from the same IP address", 1}; boost::optional> get_proxies(boost::program_options::variables_map const& vm) { diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 1b0e3f261..95f3ddd40 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -163,6 +163,10 @@ namespace cryptonote command_line::add_arg(desc, arg_rpc_payment_difficulty); command_line::add_arg(desc, arg_rpc_payment_credits); command_line::add_arg(desc, arg_rpc_payment_allow_free_loopback); + command_line::add_arg(desc, arg_rpc_max_connections_per_public_ip); + command_line::add_arg(desc, arg_rpc_max_connections_per_private_ip); + command_line::add_arg(desc, arg_rpc_max_connections); + command_line::add_arg(desc, arg_rpc_response_soft_limit); } //------------------------------------------------------------------------------------------------------------------------------ core_rpc_server::core_rpc_server( @@ -369,11 +373,28 @@ namespace cryptonote } } + const auto max_connections_public = command_line::get_arg(vm, arg_rpc_max_connections_per_public_ip); + const auto max_connections_private = command_line::get_arg(vm, arg_rpc_max_connections_per_private_ip); + const auto max_connections = command_line::get_arg(vm, arg_rpc_max_connections); + + if (max_connections < max_connections_public) + { + MFATAL(arg_rpc_max_connections_per_public_ip.name << " is bigger than " << arg_rpc_max_connections.name); + return false; + } + if (max_connections < max_connections_private) + { + MFATAL(arg_rpc_max_connections_per_private_ip.name << " is bigger than " << arg_rpc_max_connections.name); + return false; + } + auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); }; const bool inited = epee::http_server_impl_base::init( rng, std::move(port), std::move(bind_ip_str), std::move(bind_ipv6_str), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4), - std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options) + std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options), + max_connections_public, max_connections_private, max_connections, + command_line::get_arg(vm, arg_rpc_response_soft_limit) ); m_net_server.get_config_object().m_max_content_length = MAX_RPC_CONTENT_LENGTH; @@ -3748,4 +3769,28 @@ namespace cryptonote , "Allow free access from the loopback address (ie, the local host)" , false }; + + const command_line::arg_descriptor core_rpc_server::arg_rpc_max_connections_per_public_ip = { + "rpc-max-connections-per-public-ip" + , "Max RPC connections per public IP permitted" + , DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP + }; + + const command_line::arg_descriptor core_rpc_server::arg_rpc_max_connections_per_private_ip = { + "rpc-max-connections-per-private-ip" + , "Max RPC connections per private and localhost IP permitted" + , DEFAULT_RPC_MAX_CONNECTIONS_PER_PRIVATE_IP + }; + + const command_line::arg_descriptor core_rpc_server::arg_rpc_max_connections = { + "rpc-max-connections" + , "Max RPC connections permitted" + , DEFAULT_RPC_MAX_CONNECTIONS + }; + + const command_line::arg_descriptor core_rpc_server::arg_rpc_response_soft_limit = { + "rpc-response-soft-limit" + , "Max response bytes that can be queued, enforced at next response attempt" + , DEFAULT_RPC_SOFT_LIMIT_SIZE + }; } // namespace cryptonote diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index b87412ca6..90c05f41a 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -56,7 +56,6 @@ namespace cryptonote { public: - static const command_line::arg_descriptor arg_public_node; static const command_line::arg_descriptor arg_rpc_bind_port; static const command_line::arg_descriptor arg_rpc_restricted_bind_port; static const command_line::arg_descriptor arg_restricted_rpc; @@ -73,6 +72,10 @@ namespace cryptonote static const command_line::arg_descriptor arg_rpc_payment_difficulty; static const command_line::arg_descriptor arg_rpc_payment_credits; static const command_line::arg_descriptor arg_rpc_payment_allow_free_loopback; + static const command_line::arg_descriptor arg_rpc_max_connections_per_public_ip; + static const command_line::arg_descriptor arg_rpc_max_connections_per_private_ip; + static const command_line::arg_descriptor arg_rpc_max_connections; + static const command_line::arg_descriptor arg_rpc_response_soft_limit; typedef epee::net_utils::connection_context_base connection_context; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 14c66c5f5..b84b7b284 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -129,6 +129,10 @@ namespace const command_line::arg_descriptor arg_wallet_dir = {"wallet-dir", "Directory for newly created wallets"}; const command_line::arg_descriptor arg_prompt_for_password = {"prompt-for-password", "Prompts for password when not provided", false}; const command_line::arg_descriptor arg_no_initial_sync = {"no-initial-sync", "Skips the initial sync before listening for connections", false}; + const command_line::arg_descriptor arg_rpc_max_connections_per_public_ip = {"rpc-max-connections-per-public-ip", "Max RPC connections per public IP permitted", DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP}; + const command_line::arg_descriptor arg_rpc_max_connections_per_private_ip = {"rpc-max-connections-per-private-ip", "Max RPC connections per private and localhost IP permitted", DEFAULT_RPC_MAX_CONNECTIONS_PER_PRIVATE_IP}; + const command_line::arg_descriptor arg_rpc_max_connections = {"rpc-max-connections", "Max RPC connections permitted", DEFAULT_RPC_MAX_CONNECTIONS}; + const command_line::arg_descriptor arg_rpc_response_soft_limit = {"rpc-response-soft-limit", "Max response bytes that can be queued, enforced at next response attempt", DEFAULT_RPC_SOFT_LIMIT_SIZE}; constexpr const char default_rpc_username[] = "monero"; @@ -325,13 +329,30 @@ namespace tools check_background_mining(); + const auto max_connections_public = command_line::get_arg(vm, arg_rpc_max_connections_per_public_ip); + const auto max_connections_private = command_line::get_arg(vm, arg_rpc_max_connections_per_private_ip); + const auto max_connections = command_line::get_arg(vm, arg_rpc_max_connections); + + if (max_connections < max_connections_public) + { + MFATAL(arg_rpc_max_connections_per_public_ip.name << " is bigger than " << arg_rpc_max_connections.name); + return false; + } + if (max_connections < max_connections_private) + { + MFATAL(arg_rpc_max_connections_per_private_ip.name << " is bigger than " << arg_rpc_max_connections.name); + return false; + } + m_net_server.set_threads_prefix("RPC"); auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); }; return epee::http_server_impl_base::init( rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->bind_ipv6_address), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4), std::move(rpc_config->access_control_origins), std::move(http_login), - std::move(rpc_config->ssl_options) + std::move(rpc_config->ssl_options), + max_connections_public, max_connections_private, max_connections, + command_line::get_arg(vm, arg_rpc_response_soft_limit) ); } //------------------------------------------------------------------------------------------------------------------------------ @@ -4940,6 +4961,10 @@ int main(int argc, char** argv) { command_line::add_arg(desc_params, arg_prompt_for_password); command_line::add_arg(desc_params, arg_rpc_client_secret_key); command_line::add_arg(desc_params, arg_no_initial_sync); + command_line::add_arg(desc_params, arg_rpc_max_connections_per_public_ip); + command_line::add_arg(desc_params, arg_rpc_max_connections_per_private_ip); + command_line::add_arg(desc_params, arg_rpc_max_connections); + command_line::add_arg(desc_params, arg_rpc_response_soft_limit); daemonizer::init_options(hidden_options, desc_params); desc_params.add(hidden_options); -- cgit v1.2.3