diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index beae55b35..fa54897a9 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -388,6 +388,7 @@ namespace cryptonote m_fluffy_blocks_enabled = !get_arg(vm, arg_no_fluffy_blocks); m_offline = get_arg(vm, arg_offline); m_disable_dns_checkpoints = get_arg(vm, arg_disable_dns_checkpoints); + if (!command_line::is_arg_defaulted(vm, arg_fluffy_blocks)) MWARNING(arg_fluffy_blocks.name << " is obsolete, it is now default"); @@ -460,7 +461,7 @@ namespace cryptonote return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm, const cryptonote::test_options *test_options, const GetCheckpointsCallback& get_checkpoints/* = nullptr */) + bool core::init(const boost::program_options::variables_map& vm, const cryptonote::test_options *test_options, const GetCheckpointsCallback& get_checkpoints/* = nullptr */, bool allow_dns) { start_time = std::time(nullptr); @@ -471,6 +472,7 @@ namespace cryptonote } bool r = handle_command_line(vm); CHECK_AND_ASSERT_MES(r, false, "Failed to handle command line"); + m_disable_dns_checkpoints |= not allow_dns; std::string db_sync_mode = command_line::get_arg(vm, cryptonote::arg_db_sync_mode); bool db_salvage = command_line::get_arg(vm, cryptonote::arg_db_salvage) != 0; @@ -697,7 +699,7 @@ namespace cryptonote CHECK_AND_ASSERT_MES(update_checkpoints(skip_dns_checkpoints), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); // DNS versions checking - if (check_updates_string == "disabled") + if (check_updates_string == "disabled" || not allow_dns) check_updates_level = UPDATES_DISABLED; else if (check_updates_string == "notify") check_updates_level = UPDATES_NOTIFY; diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 8891540a9..5a73be7fc 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -276,10 +276,11 @@ namespace cryptonote * @param vm command line parameters * @param test_options configuration options for testing * @param get_checkpoints if set, will be called to get checkpoints data, must return checkpoints data pointer and size or nullptr if there ain't any checkpoints for specific network type + * @param allow_dns whether or not to allow DNS requests * * @return false if one of the init steps fails, otherwise true */ - bool init(const boost::program_options::variables_map& vm, const test_options *test_options = NULL, const GetCheckpointsCallback& get_checkpoints = nullptr); + bool init(const boost::program_options::variables_map& vm, const test_options *test_options = NULL, const GetCheckpointsCallback& get_checkpoints = nullptr, bool allow_dns = true); /** * @copydoc Blockchain::reset_and_set_genesis_block diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index 6c3e163e6..a988fe25f 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -96,6 +96,16 @@ namespace daemon_args , 0 }; + const command_line::arg_descriptor arg_proxy = { + "proxy", + "Network communication through proxy: i.e. \"127.0.0.1:9050\"", + "", + }; + const command_line::arg_descriptor arg_proxy_allow_dns_leaks = { + "proxy-allow-dns-leaks", + "Allow DNS leaks outside of proxy", + false, + }; const command_line::arg_descriptor arg_public_node = { "public-node" , "Allow other users to use the node as a remote (restricted RPC mode, view-only commands) and advertise it over P2P" diff --git a/src/daemon/core.h b/src/daemon/core.h index 804d7474d..0811cf420 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -32,6 +32,7 @@ #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "misc_log_ex.h" +#include "daemon/command_line_args.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "daemon" @@ -66,7 +67,14 @@ public: #else const cryptonote::GetCheckpointsCallback& get_checkpoints = nullptr; #endif - if (!m_core.init(m_vm_HACK, nullptr, get_checkpoints)) + + if (command_line::is_arg_defaulted(vm, daemon_args::arg_proxy) && command_line::get_arg(vm, daemon_args::arg_proxy_allow_dns_leaks)) { + MLOG_RED(el::Level::Warning, "--" << daemon_args::arg_proxy_allow_dns_leaks.name << " is enabled, but --" + << daemon_args::arg_proxy.name << " is not specified."); + } + + const bool allow_dns = command_line::is_arg_defaulted(vm, daemon_args::arg_proxy) || command_line::get_arg(vm, daemon_args::arg_proxy_allow_dns_leaks); + if (!m_core.init(m_vm_HACK, nullptr, get_checkpoints, allow_dns)) { throw std::runtime_error("Failed to initialize core"); } diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index d413906df..70aec5538 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -152,6 +152,8 @@ int main(int argc, char const * argv[]) command_line::add_arg(core_settings, daemon_args::arg_max_log_file_size); command_line::add_arg(core_settings, daemon_args::arg_max_log_files); command_line::add_arg(core_settings, daemon_args::arg_max_concurrency); + command_line::add_arg(core_settings, daemon_args::arg_proxy); + command_line::add_arg(core_settings, daemon_args::arg_proxy_allow_dns_leaks); command_line::add_arg(core_settings, daemon_args::arg_public_node); 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); diff --git a/src/daemon/p2p.h b/src/daemon/p2p.h index f68efccc2..38862c017 100644 --- a/src/daemon/p2p.h +++ b/src/daemon/p2p.h @@ -33,6 +33,7 @@ #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "p2p/net_node.h" #include "daemon/protocol.h" +#include "daemon/command_line_args.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "daemon" @@ -61,7 +62,7 @@ public: { //initialize objects MGINFO("Initializing p2p server..."); - if (!m_server.init(vm)) + if (!m_server.init(vm, command_line::get_arg(vm, daemon_args::arg_proxy), command_line::get_arg(vm, daemon_args::arg_proxy_allow_dns_leaks))) { throw std::runtime_error("Failed to initialize p2p server."); } diff --git a/src/daemon/rpc.h b/src/daemon/rpc.h index af48bcc45..bff7dc449 100644 --- a/src/daemon/rpc.h +++ b/src/daemon/rpc.h @@ -62,7 +62,7 @@ public: { MGINFO("Initializing " << m_description << " RPC server..."); - if (!m_server.init(vm, restricted, port, allow_rpc_payment)) + if (!m_server.init(vm, restricted, port, allow_rpc_payment, command_line::get_arg(vm, daemon_args::arg_proxy))) { throw std::runtime_error("Failed to initialize " + m_description + " RPC server."); } diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index 84cc1581e..c951db085 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -94,6 +94,9 @@ namespace case net::i2p_address::get_type_id(): set = client->set_connect_command(remote.as()); break; + case epee::net_utils::ipv4_network_address::get_type_id(): + set = client->set_connect_command(remote.as()); + break; default: MERROR("Unsupported network address in socks_connect"); return false; diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index f2888674b..9e64121be 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -259,6 +259,7 @@ namespace nodetool m_offline(false), is_closing(false), m_network_id(), + m_enable_dns_seed_nodes(true), max_connections(1) {} virtual ~node_server(); @@ -267,7 +268,7 @@ namespace nodetool bool run(); network_zone& add_zone(epee::net_utils::zone zone); - bool init(const boost::program_options::variables_map& vm); + bool init(const boost::program_options::variables_map& vm, const std::string& proxy = {}, bool proxy_dns_leaks_allowed = {}); bool deinit(); bool send_stop_signal(); uint32_t get_this_peer_port(){return m_listening_port;} @@ -516,6 +517,7 @@ namespace nodetool epee::net_utils::ssl_support_t m_ssl_support; + bool m_enable_dns_seed_nodes; bool m_enable_dns_blocklist; uint32_t max_connections; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index a0b8438b2..e2b1f3c9c 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -723,6 +723,12 @@ namespace nodetool { return get_ip_seed_nodes(); } + if (!m_enable_dns_seed_nodes) + { + // TODO: a domain can be set through socks, so that the remote side does the lookup for the DNS seed nodes. + m_fallback_seed_nodes_added.test_and_set(); + return get_ip_seed_nodes(); + } std::set full_addrs; @@ -861,10 +867,21 @@ namespace nodetool } //----------------------------------------------------------------------------------- template - bool node_server::init(const boost::program_options::variables_map& vm) + bool node_server::init(const boost::program_options::variables_map& vm, const std::string& proxy, bool proxy_dns_leaks_allowed) { bool res = handle_command_line(vm); CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line"); + if (proxy.size()) + { + const auto endpoint = net::get_tcp_endpoint(proxy); + CHECK_AND_ASSERT_MES(endpoint, false, "Failed to parse proxy: " << proxy << " - " << endpoint.error()); + network_zone& public_zone = m_network_zones[epee::net_utils::zone::public_]; + public_zone.m_connect = &socks_connect; + public_zone.m_proxy_address = *endpoint; + public_zone.m_can_pingback = false; + m_enable_dns_seed_nodes &= proxy_dns_leaks_allowed; + m_enable_dns_blocklist &= proxy_dns_leaks_allowed; + } if (m_nettype == cryptonote::TESTNET) { diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index ded545efa..684900e96 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -242,11 +242,11 @@ namespace cryptonote auto get_nodes = [this]() { return get_public_nodes(credits_per_hash_threshold); }; - m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled, proxy)); + m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled, m_bootstrap_daemon_proxy.empty() ? proxy : m_bootstrap_daemon_proxy)); } else { - m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled, proxy)); + m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled, m_bootstrap_daemon_proxy.empty() ? proxy : m_bootstrap_daemon_proxy)); } m_should_use_bootstrap_daemon = m_bootstrap_daemon.get() != nullptr; @@ -264,8 +264,10 @@ namespace cryptonote , const bool restricted , const std::string& port , bool allow_rpc_payment + , const std::string& proxy ) { + m_bootstrap_daemon_proxy = proxy; m_restricted = restricted; m_net_server.set_threads_prefix("RPC"); m_net_server.set_connection_filter(&m_p2p); diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index b21e43ab0..db1429ab1 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -91,7 +91,8 @@ namespace cryptonote const boost::program_options::variables_map& vm, const bool restricted, const std::string& port, - bool allow_rpc_payment + bool allow_rpc_payment, + const std::string& proxy = {} ); network_type nettype() const { return m_core.get_nettype(); } @@ -289,6 +290,7 @@ private: nodetool::node_server >& m_p2p; boost::shared_mutex m_bootstrap_daemon_mutex; std::unique_ptr m_bootstrap_daemon; + std::string m_bootstrap_daemon_proxy; bool m_should_use_bootstrap_daemon; std::chrono::system_clock::time_point m_bootstrap_height_check_time; bool m_was_bootstrap_ever_used;