mirror of
https://github.com/monero-project/monero.git
synced 2026-08-03 01:15:55 -07:00
@@ -68,7 +68,7 @@ namespace {
|
||||
std::string id_str;
|
||||
std::string port_str;
|
||||
std::string elapsed = peer.last_seen == 0 ? "never" : epee::misc_utils::get_time_interval_string(now - last_seen);
|
||||
std::string ip_str = epee::string_tools::get_ip_string_from_int32(peer.ip);
|
||||
std::string ip_str = peer.ip != 0 ? epee::string_tools::get_ip_string_from_int32(peer.ip) : std::string("[") + peer.host + "]";
|
||||
std::stringstream peer_id_str;
|
||||
peer_id_str << std::hex << std::setw(16) << peer.id;
|
||||
peer_id_str >> id_str;
|
||||
|
||||
+50
-9
@@ -34,28 +34,69 @@
|
||||
|
||||
namespace net
|
||||
{
|
||||
void get_network_address_host_and_port(const std::string& address, std::string& host, std::string& port)
|
||||
{
|
||||
// require ipv6 address format "[addr:addr:addr:...:addr]:port"
|
||||
if (address.find(']') != std::string::npos)
|
||||
{
|
||||
host = address.substr(1, address.rfind(']') - 1);
|
||||
if ((host.size() + 2) < address.size())
|
||||
{
|
||||
port = address.substr(address.rfind(':') + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
host = address.substr(0, address.rfind(':'));
|
||||
if (host.size() < address.size())
|
||||
{
|
||||
port = address.substr(host.size() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect<epee::net_utils::network_address>
|
||||
get_network_address(const boost::string_ref address, const std::uint16_t default_port)
|
||||
{
|
||||
const boost::string_ref host = address.substr(0, address.rfind(':'));
|
||||
std::string host_str = "";
|
||||
std::string port_str = "";
|
||||
|
||||
if (host.empty())
|
||||
bool ipv6 = false;
|
||||
|
||||
get_network_address_host_and_port(std::string(address), host_str, port_str);
|
||||
|
||||
boost::string_ref host_str_ref(host_str);
|
||||
boost::string_ref port_str_ref(port_str);
|
||||
|
||||
if (host_str.empty())
|
||||
return make_error_code(net::error::invalid_host);
|
||||
if (host.ends_with(".onion"))
|
||||
if (host_str_ref.ends_with(".onion"))
|
||||
return tor_address::make(address, default_port);
|
||||
if (host.ends_with(".i2p"))
|
||||
if (host_str_ref.ends_with(".i2p"))
|
||||
return i2p_address::make(address, default_port);
|
||||
|
||||
boost::system::error_code ec;
|
||||
boost::asio::ip::address_v6 v6 = boost::asio::ip::make_address_v6(host_str, ec);
|
||||
ipv6 = !ec;
|
||||
|
||||
std::uint16_t port = default_port;
|
||||
if (host.size() < address.size())
|
||||
if (port_str.size())
|
||||
{
|
||||
if (!epee::string_tools::get_xtype_from_string(port, std::string{address.substr(host.size() + 1)}))
|
||||
if (!epee::string_tools::get_xtype_from_string(port, port_str))
|
||||
return make_error_code(net::error::invalid_port);
|
||||
}
|
||||
|
||||
std::uint32_t ip = 0;
|
||||
if (epee::string_tools::get_ip_int32_from_string(ip, std::string{host}))
|
||||
return {epee::net_utils::ipv4_network_address{ip, port}};
|
||||
if (ipv6)
|
||||
{
|
||||
return {epee::net_utils::ipv6_network_address{v6, port}};
|
||||
}
|
||||
else
|
||||
{
|
||||
std::uint32_t ip = 0;
|
||||
if (epee::string_tools::get_ip_int32_from_string(ip, host_str))
|
||||
return {epee::net_utils::ipv4_network_address{ip, port}};
|
||||
}
|
||||
|
||||
return make_error_code(net::error::unsupported_address);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
namespace net
|
||||
{
|
||||
void get_network_address_host_and_port(const std::string& address, std::string& host, std::string& port);
|
||||
|
||||
/*!
|
||||
Identifies onion, i2p and IPv4 addresses and returns them as a generic
|
||||
`network_address`. If the type is unsupported, it might be a hostname,
|
||||
|
||||
+19
-2
@@ -108,10 +108,11 @@ namespace
|
||||
|
||||
namespace nodetool
|
||||
{
|
||||
const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"};
|
||||
const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol (IPv4)", "0.0.0.0"};
|
||||
const command_line::arg_descriptor<std::string> arg_p2p_bind_ipv6_address = {"p2p-bind-ipv6-address", "Interface for p2p network protocol (IPv6)", "::"};
|
||||
const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port = {
|
||||
"p2p-bind-port"
|
||||
, "Port for p2p network protocol"
|
||||
, "Port for p2p network protocol (IPv4)"
|
||||
, std::to_string(config::P2P_DEFAULT_PORT)
|
||||
, {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }}
|
||||
, [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string {
|
||||
@@ -122,6 +123,20 @@ namespace nodetool
|
||||
return val;
|
||||
}
|
||||
};
|
||||
const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port_ipv6 = {
|
||||
"p2p-bind-port-ipv6"
|
||||
, "Port for p2p network protocol (IPv6)"
|
||||
, std::to_string(config::P2P_DEFAULT_PORT)
|
||||
, {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }}
|
||||
, [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string {
|
||||
if (testnet_stagenet[0] && defaulted)
|
||||
return std::to_string(config::testnet::P2P_DEFAULT_PORT);
|
||||
else if (testnet_stagenet[1] && defaulted)
|
||||
return std::to_string(config::stagenet::P2P_DEFAULT_PORT);
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
const command_line::arg_descriptor<uint32_t> arg_p2p_external_port = {"p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
|
||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
|
||||
@@ -136,6 +151,8 @@ namespace nodetool
|
||||
|
||||
const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
|
||||
const command_line::arg_descriptor<std::string> arg_igd = {"igd", "UPnP port mapping (disabled, enabled, delayed)", "delayed"};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_use_ipv6 = {"p2p-use-ipv6", "Enable IPv6 for p2p", false};
|
||||
const command_line::arg_descriptor<bool> arg_p2p_require_ipv4 = {"p2p-require-ipv4", "Require successful IPv4 bind for p2p", true};
|
||||
const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max number of out peers", -1};
|
||||
const command_line::arg_descriptor<int64_t> arg_in_peers = {"in-peers", "set max number of in peers", -1};
|
||||
const command_line::arg_descriptor<int> arg_tos_flag = {"tos-flag", "set TOS flag", -1};
|
||||
|
||||
+20
-1
@@ -151,7 +151,9 @@ namespace nodetool
|
||||
: m_connect(nullptr),
|
||||
m_net_server(epee::net_utils::e_connection_type_P2P),
|
||||
m_bind_ip(),
|
||||
m_bind_ipv6_address(),
|
||||
m_port(),
|
||||
m_port_ipv6(),
|
||||
m_our_address(),
|
||||
m_peerlist(),
|
||||
m_config{},
|
||||
@@ -167,7 +169,9 @@ namespace nodetool
|
||||
: m_connect(nullptr),
|
||||
m_net_server(public_service, epee::net_utils::e_connection_type_P2P),
|
||||
m_bind_ip(),
|
||||
m_bind_ipv6_address(),
|
||||
m_port(),
|
||||
m_port_ipv6(),
|
||||
m_our_address(),
|
||||
m_peerlist(),
|
||||
m_config{},
|
||||
@@ -182,7 +186,9 @@ namespace nodetool
|
||||
connect_func* m_connect;
|
||||
net_server m_net_server;
|
||||
std::string m_bind_ip;
|
||||
std::string m_bind_ipv6_address;
|
||||
std::string m_port;
|
||||
std::string m_port_ipv6;
|
||||
epee::net_utils::network_address m_our_address; // in anonymity networks
|
||||
peerlist_manager m_peerlist;
|
||||
config m_config;
|
||||
@@ -357,7 +363,13 @@ namespace nodetool
|
||||
bool is_peer_used(const peerlist_entry& peer);
|
||||
bool is_peer_used(const anchor_peerlist_entry& peer);
|
||||
bool is_addr_connected(const epee::net_utils::network_address& peer);
|
||||
void add_upnp_port_mapping(uint32_t port);
|
||||
void add_upnp_port_mapping_impl(uint32_t port, bool ipv6=false);
|
||||
void add_upnp_port_mapping_v4(uint32_t port);
|
||||
void add_upnp_port_mapping_v6(uint32_t port);
|
||||
void add_upnp_port_mapping(uint32_t port, bool ipv4=true, bool ipv6=false);
|
||||
void delete_upnp_port_mapping_impl(uint32_t port, bool ipv6=false);
|
||||
void delete_upnp_port_mapping_v4(uint32_t port);
|
||||
void delete_upnp_port_mapping_v6(uint32_t port);
|
||||
void delete_upnp_port_mapping(uint32_t port);
|
||||
template<class t_callback>
|
||||
bool try_ping(basic_node_data& node_data, p2p_connection_context& context, const t_callback &cb);
|
||||
@@ -419,12 +431,15 @@ namespace nodetool
|
||||
bool m_have_address;
|
||||
bool m_first_connection_maker_call;
|
||||
uint32_t m_listening_port;
|
||||
uint32_t m_listening_port_ipv6;
|
||||
uint32_t m_external_port;
|
||||
uint16_t m_rpc_port;
|
||||
bool m_allow_local_ip;
|
||||
bool m_hide_my_port;
|
||||
igd_t m_igd;
|
||||
bool m_offline;
|
||||
bool m_use_ipv6;
|
||||
bool m_require_ipv4;
|
||||
std::atomic<bool> is_closing;
|
||||
std::unique_ptr<boost::thread> mPeersLoggerThread;
|
||||
//critical_section m_connections_lock;
|
||||
@@ -485,7 +500,11 @@ namespace nodetool
|
||||
const int64_t default_limit_up = P2P_DEFAULT_LIMIT_RATE_UP; // kB/s
|
||||
const int64_t default_limit_down = P2P_DEFAULT_LIMIT_RATE_DOWN; // kB/s
|
||||
extern const command_line::arg_descriptor<std::string> arg_p2p_bind_ip;
|
||||
extern const command_line::arg_descriptor<std::string> arg_p2p_bind_ipv6_address;
|
||||
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port;
|
||||
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port_ipv6;
|
||||
extern const command_line::arg_descriptor<bool> arg_p2p_use_ipv6;
|
||||
extern const command_line::arg_descriptor<bool> arg_p2p_require_ipv4;
|
||||
extern const command_line::arg_descriptor<uint32_t> arg_p2p_external_port;
|
||||
extern const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip;
|
||||
extern const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer;
|
||||
|
||||
+161
-31
@@ -93,7 +93,11 @@ namespace nodetool
|
||||
void node_server<t_payload_net_handler>::init_options(boost::program_options::options_description& desc)
|
||||
{
|
||||
command_line::add_arg(desc, arg_p2p_bind_ip);
|
||||
command_line::add_arg(desc, arg_p2p_bind_ipv6_address);
|
||||
command_line::add_arg(desc, arg_p2p_bind_port, false);
|
||||
command_line::add_arg(desc, arg_p2p_bind_port_ipv6, false);
|
||||
command_line::add_arg(desc, arg_p2p_use_ipv6);
|
||||
command_line::add_arg(desc, arg_p2p_require_ipv4);
|
||||
command_line::add_arg(desc, arg_p2p_external_port);
|
||||
command_line::add_arg(desc, arg_p2p_allow_local_ip);
|
||||
command_line::add_arg(desc, arg_p2p_add_peer);
|
||||
@@ -341,7 +345,9 @@ namespace nodetool
|
||||
network_zone& public_zone = m_network_zones[epee::net_utils::zone::public_];
|
||||
public_zone.m_connect = &public_connect;
|
||||
public_zone.m_bind_ip = command_line::get_arg(vm, arg_p2p_bind_ip);
|
||||
public_zone.m_bind_ipv6_address = command_line::get_arg(vm, arg_p2p_bind_ipv6_address);
|
||||
public_zone.m_port = command_line::get_arg(vm, arg_p2p_bind_port);
|
||||
public_zone.m_port_ipv6 = command_line::get_arg(vm, arg_p2p_bind_port_ipv6);
|
||||
public_zone.m_can_pingback = true;
|
||||
m_external_port = command_line::get_arg(vm, arg_p2p_external_port);
|
||||
m_allow_local_ip = command_line::get_arg(vm, arg_p2p_allow_local_ip);
|
||||
@@ -375,6 +381,8 @@ namespace nodetool
|
||||
return false;
|
||||
}
|
||||
m_offline = command_line::get_arg(vm, cryptonote::arg_offline);
|
||||
m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
|
||||
m_require_ipv4 = command_line::get_arg(vm, arg_p2p_require_ipv4);
|
||||
|
||||
if (command_line::has_arg(vm, arg_p2p_add_peer))
|
||||
{
|
||||
@@ -518,12 +526,17 @@ namespace nodetool
|
||||
|
||||
std::string host = addr;
|
||||
std::string port = std::to_string(default_port);
|
||||
size_t pos = addr.find_last_of(':');
|
||||
if (std::string::npos != pos)
|
||||
size_t colon_pos = addr.find_last_of(':');
|
||||
size_t dot_pos = addr.find_last_of('.');
|
||||
size_t square_brace_pos = addr.find('[');
|
||||
|
||||
// IPv6 will have colons regardless. IPv6 and IPv4 address:port will have a colon but also either a . or a [
|
||||
// as IPv6 addresses specified as address:port are to be specified as "[addr:addr:...:addr]:port"
|
||||
// One may also specify an IPv6 address as simply "[addr:addr:...:addr]" without the port; in that case
|
||||
// the square braces will be stripped here.
|
||||
if ((std::string::npos != colon_pos && std::string::npos != dot_pos) || std::string::npos != square_brace_pos)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(addr.length() - 1 != pos && 0 != pos, false, "Failed to parse seed address from string: '" << addr << '\'');
|
||||
host = addr.substr(0, pos);
|
||||
port = addr.substr(pos + 1);
|
||||
net::get_network_address_host_and_port(addr, host, port);
|
||||
}
|
||||
MINFO("Resolving node address: host=" << host << ", port=" << port);
|
||||
|
||||
@@ -546,7 +559,9 @@ namespace nodetool
|
||||
}
|
||||
else
|
||||
{
|
||||
MWARNING("IPv6 unsupported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec));
|
||||
epee::net_utils::network_address na{epee::net_utils::ipv6_network_address{endpoint.address().to_v6(), endpoint.port()}};
|
||||
seed_nodes.push_back(na);
|
||||
MINFO("Added node: " << na.str());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -780,21 +795,40 @@ namespace nodetool
|
||||
|
||||
if (!zone.second.m_bind_ip.empty())
|
||||
{
|
||||
std::string ipv6_addr = "";
|
||||
std::string ipv6_port = "";
|
||||
zone.second.m_net_server.set_connection_filter(this);
|
||||
MINFO("Binding on " << zone.second.m_bind_ip << ":" << zone.second.m_port);
|
||||
res = zone.second.m_net_server.init_server(zone.second.m_port, zone.second.m_bind_ip, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
|
||||
MINFO("Binding (IPv4) on " << zone.second.m_bind_ip << ":" << zone.second.m_port);
|
||||
if (!zone.second.m_bind_ipv6_address.empty() && m_use_ipv6)
|
||||
{
|
||||
ipv6_addr = zone.second.m_bind_ipv6_address;
|
||||
ipv6_port = zone.second.m_port_ipv6;
|
||||
MINFO("Binding (IPv6) on " << zone.second.m_bind_ipv6_address << ":" << zone.second.m_port_ipv6);
|
||||
}
|
||||
res = zone.second.m_net_server.init_server(zone.second.m_port, zone.second.m_bind_ip, ipv6_port, ipv6_addr, m_use_ipv6, m_require_ipv4, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to bind server");
|
||||
}
|
||||
}
|
||||
|
||||
m_listening_port = public_zone.m_net_server.get_binded_port();
|
||||
MLOG_GREEN(el::Level::Info, "Net service bound to " << public_zone.m_bind_ip << ":" << m_listening_port);
|
||||
MLOG_GREEN(el::Level::Info, "Net service bound (IPv4) to " << public_zone.m_bind_ip << ":" << m_listening_port);
|
||||
if (m_use_ipv6)
|
||||
{
|
||||
m_listening_port_ipv6 = public_zone.m_net_server.get_binded_port_ipv6();
|
||||
MLOG_GREEN(el::Level::Info, "Net service bound (IPv6) to " << public_zone.m_bind_ipv6_address << ":" << m_listening_port_ipv6);
|
||||
}
|
||||
if(m_external_port)
|
||||
MDEBUG("External port defined as " << m_external_port);
|
||||
|
||||
// add UPnP port mapping
|
||||
if(m_igd == igd)
|
||||
add_upnp_port_mapping(m_listening_port);
|
||||
{
|
||||
add_upnp_port_mapping_v4(m_listening_port);
|
||||
if (m_use_ipv6)
|
||||
{
|
||||
add_upnp_port_mapping_v6(m_listening_port_ipv6);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1997,19 +2031,43 @@ namespace nodetool
|
||||
if(!node_data.my_port)
|
||||
return false;
|
||||
|
||||
CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(), false,
|
||||
"Only IPv4 addresses are supported here");
|
||||
bool address_ok = (context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id() || context.m_remote_address.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id());
|
||||
CHECK_AND_ASSERT_MES(address_ok, false,
|
||||
"Only IPv4 or IPv6 addresses are supported here");
|
||||
|
||||
const epee::net_utils::network_address na = context.m_remote_address;
|
||||
uint32_t actual_ip = na.as<const epee::net_utils::ipv4_network_address>().ip();
|
||||
std::string ip;
|
||||
uint32_t ipv4_addr;
|
||||
boost::asio::ip::address_v6 ipv6_addr;
|
||||
bool is_ipv4;
|
||||
if (na.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
|
||||
{
|
||||
ipv4_addr = na.as<const epee::net_utils::ipv4_network_address>().ip();
|
||||
ip = epee::string_tools::get_ip_string_from_int32(ipv4_addr);
|
||||
is_ipv4 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ipv6_addr = na.as<const epee::net_utils::ipv6_network_address>().ip();
|
||||
ip = ipv6_addr.to_string();
|
||||
is_ipv4 = false;
|
||||
}
|
||||
network_zone& zone = m_network_zones.at(na.get_zone());
|
||||
|
||||
if(!zone.m_peerlist.is_host_allowed(context.m_remote_address))
|
||||
return false;
|
||||
|
||||
std::string ip = epee::string_tools::get_ip_string_from_int32(actual_ip);
|
||||
std::string port = epee::string_tools::num_to_string_fast(node_data.my_port);
|
||||
epee::net_utils::network_address address{epee::net_utils::ipv4_network_address(actual_ip, node_data.my_port)};
|
||||
|
||||
epee::net_utils::network_address address;
|
||||
if (is_ipv4)
|
||||
{
|
||||
address = epee::net_utils::network_address{epee::net_utils::ipv4_network_address(ipv4_addr, node_data.my_port)};
|
||||
}
|
||||
else
|
||||
{
|
||||
address = epee::net_utils::network_address{epee::net_utils::ipv6_network_address(ipv6_addr, node_data.my_port)};
|
||||
}
|
||||
peerid_type pr = node_data.peer_id;
|
||||
bool r = zone.m_net_server.connect_async(ip, port, zone.m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ address, pr, this](
|
||||
const typename net_server::t_connection_context& ping_context,
|
||||
@@ -2193,12 +2251,19 @@ namespace nodetool
|
||||
//try ping to be sure that we can add this peer to peer_list
|
||||
try_ping(arg.node_data, context, [peer_id_l, port_l, context, this]()
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(), void(),
|
||||
"Only IPv4 addresses are supported here");
|
||||
CHECK_AND_ASSERT_MES((context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id() || context.m_remote_address.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id()), void(),
|
||||
"Only IPv4 or IPv6 addresses are supported here");
|
||||
//called only(!) if success pinged, update local peerlist
|
||||
peerlist_entry pe;
|
||||
const epee::net_utils::network_address na = context.m_remote_address;
|
||||
pe.adr = epee::net_utils::ipv4_network_address(na.as<epee::net_utils::ipv4_network_address>().ip(), port_l);
|
||||
if (context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
|
||||
{
|
||||
pe.adr = epee::net_utils::ipv4_network_address(na.as<epee::net_utils::ipv4_network_address>().ip(), port_l);
|
||||
}
|
||||
else
|
||||
{
|
||||
pe.adr = epee::net_utils::ipv6_network_address(na.as<epee::net_utils::ipv6_network_address>().ip(), port_l);
|
||||
}
|
||||
time_t last_seen;
|
||||
time(&last_seen);
|
||||
pe.last_seen = static_cast<int64_t>(last_seen);
|
||||
@@ -2565,16 +2630,19 @@ namespace nodetool
|
||||
}
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::add_upnp_port_mapping(uint32_t port)
|
||||
void node_server<t_payload_net_handler>::add_upnp_port_mapping_impl(uint32_t port, bool ipv6) // if ipv6 false, do ipv4
|
||||
{
|
||||
MDEBUG("Attempting to add IGD port mapping.");
|
||||
std::string ipversion = ipv6 ? "(IPv6)" : "(IPv4)";
|
||||
MDEBUG("Attempting to add IGD port mapping " << ipversion << ".");
|
||||
int result;
|
||||
const int ipv6_arg = ipv6 ? 1 : 0;
|
||||
|
||||
#if MINIUPNPC_API_VERSION > 13
|
||||
// default according to miniupnpc.h
|
||||
unsigned char ttl = 2;
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, ttl, &result);
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, ipv6_arg, ttl, &result);
|
||||
#else
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, &result);
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, ipv6_arg, &result);
|
||||
#endif
|
||||
UPNPUrls urls;
|
||||
IGDdatas igdData;
|
||||
@@ -2611,16 +2679,38 @@ namespace nodetool
|
||||
}
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::delete_upnp_port_mapping(uint32_t port)
|
||||
void node_server<t_payload_net_handler>::add_upnp_port_mapping_v4(uint32_t port)
|
||||
{
|
||||
MDEBUG("Attempting to delete IGD port mapping.");
|
||||
add_upnp_port_mapping_impl(port, false);
|
||||
}
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::add_upnp_port_mapping_v6(uint32_t port)
|
||||
{
|
||||
add_upnp_port_mapping_impl(port, true);
|
||||
}
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::add_upnp_port_mapping(uint32_t port, bool ipv4, bool ipv6)
|
||||
{
|
||||
if (ipv4) add_upnp_port_mapping_v4(port);
|
||||
if (ipv6) add_upnp_port_mapping_v6(port);
|
||||
}
|
||||
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::delete_upnp_port_mapping_impl(uint32_t port, bool ipv6)
|
||||
{
|
||||
std::string ipversion = ipv6 ? "(IPv6)" : "(IPv4)";
|
||||
MDEBUG("Attempting to delete IGD port mapping " << ipversion << ".");
|
||||
int result;
|
||||
const int ipv6_arg = ipv6 ? 1 : 0;
|
||||
#if MINIUPNPC_API_VERSION > 13
|
||||
// default according to miniupnpc.h
|
||||
unsigned char ttl = 2;
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, ttl, &result);
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, ipv6_arg, ttl, &result);
|
||||
#else
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, 0, &result);
|
||||
UPNPDev* deviceList = upnpDiscover(1000, NULL, NULL, 0, ipv6_arg, &result);
|
||||
#endif
|
||||
UPNPUrls urls;
|
||||
IGDdatas igdData;
|
||||
@@ -2653,6 +2743,25 @@ namespace nodetool
|
||||
}
|
||||
}
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::delete_upnp_port_mapping_v4(uint32_t port)
|
||||
{
|
||||
delete_upnp_port_mapping_impl(port, false);
|
||||
}
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::delete_upnp_port_mapping_v6(uint32_t port)
|
||||
{
|
||||
delete_upnp_port_mapping_impl(port, true);
|
||||
}
|
||||
|
||||
template<class t_payload_net_handler>
|
||||
void node_server<t_payload_net_handler>::delete_upnp_port_mapping(uint32_t port)
|
||||
{
|
||||
delete_upnp_port_mapping_v4(port);
|
||||
delete_upnp_port_mapping_v6(port);
|
||||
}
|
||||
|
||||
template<typename t_payload_net_handler>
|
||||
boost::optional<p2p_connection_context_t<typename t_payload_net_handler::connection_context>>
|
||||
node_server<t_payload_net_handler>::socks_connect(network_zone& zone, const epee::net_utils::network_address& remote, epee::net_utils::ssl_support_t ssl_support)
|
||||
@@ -2671,13 +2780,34 @@ namespace nodetool
|
||||
boost::optional<p2p_connection_context_t<typename t_payload_net_handler::connection_context>>
|
||||
node_server<t_payload_net_handler>::public_connect(network_zone& zone, epee::net_utils::network_address const& na, epee::net_utils::ssl_support_t ssl_support)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(), boost::none,
|
||||
"Only IPv4 addresses are supported here");
|
||||
const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>();
|
||||
bool is_ipv4 = na.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id();
|
||||
bool is_ipv6 = na.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id();
|
||||
CHECK_AND_ASSERT_MES(is_ipv4 || is_ipv6, boost::none,
|
||||
"Only IPv4 or IPv6 addresses are supported here");
|
||||
|
||||
std::string address;
|
||||
std::string port;
|
||||
|
||||
if (is_ipv4)
|
||||
{
|
||||
const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>();
|
||||
address = epee::string_tools::get_ip_string_from_int32(ipv4.ip());
|
||||
port = epee::string_tools::num_to_string_fast(ipv4.port());
|
||||
}
|
||||
else if (is_ipv6)
|
||||
{
|
||||
const epee::net_utils::ipv6_network_address &ipv6 = na.as<const epee::net_utils::ipv6_network_address>();
|
||||
address = ipv6.ip().to_string();
|
||||
port = epee::string_tools::num_to_string_fast(ipv6.port());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Only IPv4 or IPv6 addresses are supported here");
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
typename net_server::t_connection_context con{};
|
||||
const bool res = zone.m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()),
|
||||
epee::string_tools::num_to_string_fast(ipv4.port()),
|
||||
const bool res = zone.m_net_server.connect(address, port,
|
||||
zone.m_config.m_net_config.connection_timeout,
|
||||
con, "0.0.0.0", ssl_support);
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ namespace boost
|
||||
case epee::net_utils::ipv4_network_address::get_type_id():
|
||||
do_serialize<epee::net_utils::ipv4_network_address>(is_saving, a, na);
|
||||
break;
|
||||
case epee::net_utils::ipv6_network_address::get_type_id():
|
||||
do_serialize<epee::net_utils::ipv6_network_address>(is_saving, a, na);
|
||||
break;
|
||||
case net::tor_address::get_type_id():
|
||||
do_serialize<net::tor_address>(is_saving, a, na);
|
||||
break;
|
||||
@@ -98,6 +101,34 @@ namespace boost
|
||||
na = epee::net_utils::ipv4_network_address{ip, port};
|
||||
}
|
||||
|
||||
template <class Archive, class ver_type>
|
||||
inline void serialize(Archive &a, boost::asio::ip::address_v6& v6, const ver_type ver)
|
||||
{
|
||||
if (typename Archive::is_saving())
|
||||
{
|
||||
auto bytes = v6.to_bytes();
|
||||
for (auto &e: bytes) a & e;
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::asio::ip::address_v6::bytes_type bytes;
|
||||
for (auto &e: bytes) a & e;
|
||||
v6 = boost::asio::ip::address_v6(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive, class ver_type>
|
||||
inline void serialize(Archive &a, epee::net_utils::ipv6_network_address& na, const ver_type ver)
|
||||
{
|
||||
boost::asio::ip::address_v6 ip{na.ip()};
|
||||
uint16_t port{na.port()};
|
||||
a & ip;
|
||||
a & port;
|
||||
if (!typename Archive::is_saving())
|
||||
na = epee::net_utils::ipv6_network_address{ip, port};
|
||||
}
|
||||
|
||||
|
||||
template <class Archive, class ver_type>
|
||||
inline void save(Archive& a, const net::tor_address& na, const ver_type)
|
||||
{
|
||||
|
||||
@@ -161,7 +161,9 @@ namespace cryptonote
|
||||
|
||||
auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
|
||||
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
|
||||
rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options)
|
||||
rng, std::move(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)
|
||||
);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1026,6 +1028,11 @@ namespace cryptonote
|
||||
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
|
||||
res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(),
|
||||
entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
||||
else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id())
|
||||
{
|
||||
res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(),
|
||||
entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
||||
}
|
||||
else
|
||||
res.white_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
||||
}
|
||||
@@ -1036,6 +1043,9 @@ namespace cryptonote
|
||||
if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id())
|
||||
res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(),
|
||||
entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
||||
else if (entry.adr.get_type_id() == epee::net_utils::ipv6_network_address::get_type_id())
|
||||
res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv6_network_address>().host_str(),
|
||||
entry.adr.as<epee::net_utils::ipv6_network_address>().port(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
||||
else
|
||||
res.gray_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen, entry.pruning_seed, entry.rpc_port);
|
||||
}
|
||||
|
||||
@@ -1200,6 +1200,9 @@ namespace cryptonote
|
||||
peer(uint64_t id, const std::string &host, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port)
|
||||
: id(id), host(host), ip(0), port(0), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed)
|
||||
{}
|
||||
peer(uint64_t id, const std::string &host, uint16_t port, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port)
|
||||
: id(id), host(host), ip(0), port(port), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed)
|
||||
{}
|
||||
peer(uint64_t id, uint32_t ip, uint16_t port, uint64_t last_seen, uint32_t pruning_seed, uint16_t rpc_port)
|
||||
: id(id), host(epee::string_tools::get_ip_string_from_int32(ip)), ip(ip), port(port), rpc_port(rpc_port), last_seen(last_seen), pruning_seed(pruning_seed)
|
||||
{}
|
||||
|
||||
@@ -90,6 +90,9 @@ namespace cryptonote
|
||||
|
||||
rpc_args::descriptors::descriptors()
|
||||
: rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify IP to bind RPC server"), "127.0.0.1"})
|
||||
, rpc_bind_ipv6_address({"rpc-bind-ipv6-address", rpc_args::tr("Specify IPv6 address to bind RPC server"), "::1"})
|
||||
, rpc_use_ipv6({"rpc-use-ipv6", rpc_args::tr("Allow IPv6 for RPC"), false})
|
||||
, rpc_require_ipv4({"rpc-require-ipv4", rpc_args::tr("Require successful IPv4 bind for RPC"), true})
|
||||
, rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true})
|
||||
, confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ip value is NOT a loopback (local) IP")})
|
||||
, rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""})
|
||||
@@ -108,6 +111,9 @@ namespace cryptonote
|
||||
{
|
||||
const descriptors arg{};
|
||||
command_line::add_arg(desc, arg.rpc_bind_ip);
|
||||
command_line::add_arg(desc, arg.rpc_bind_ipv6_address);
|
||||
command_line::add_arg(desc, arg.rpc_use_ipv6);
|
||||
command_line::add_arg(desc, arg.rpc_require_ipv4);
|
||||
command_line::add_arg(desc, arg.rpc_login);
|
||||
command_line::add_arg(desc, arg.confirm_external_bind);
|
||||
command_line::add_arg(desc, arg.rpc_access_control_origins);
|
||||
@@ -127,6 +133,9 @@ namespace cryptonote
|
||||
rpc_args config{};
|
||||
|
||||
config.bind_ip = command_line::get_arg(vm, arg.rpc_bind_ip);
|
||||
config.bind_ipv6_address = command_line::get_arg(vm, arg.rpc_bind_ipv6_address);
|
||||
config.use_ipv6 = command_line::get_arg(vm, arg.rpc_use_ipv6);
|
||||
config.require_ipv4 = command_line::get_arg(vm, arg.rpc_require_ipv4);
|
||||
if (!config.bind_ip.empty())
|
||||
{
|
||||
// always parse IP here for error consistency
|
||||
@@ -148,6 +157,34 @@ namespace cryptonote
|
||||
return boost::none;
|
||||
}
|
||||
}
|
||||
if (!config.bind_ipv6_address.empty())
|
||||
{
|
||||
// allow square braces, but remove them here if present
|
||||
if (config.bind_ipv6_address.find('[') != std::string::npos)
|
||||
{
|
||||
config.bind_ipv6_address = config.bind_ipv6_address.substr(1, config.bind_ipv6_address.size() - 2);
|
||||
}
|
||||
|
||||
|
||||
// always parse IP here for error consistency
|
||||
boost::system::error_code ec{};
|
||||
const auto parsed_ip = boost::asio::ip::address::from_string(config.bind_ipv6_address, ec);
|
||||
if (ec)
|
||||
{
|
||||
LOG_ERROR(tr("Invalid IP address given for --") << arg.rpc_bind_ipv6_address.name);
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
if (!parsed_ip.is_loopback() && !command_line::get_arg(vm, arg.confirm_external_bind))
|
||||
{
|
||||
LOG_ERROR(
|
||||
"--" << arg.rpc_bind_ipv6_address.name <<
|
||||
tr(" permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --") <<
|
||||
arg.confirm_external_bind.name
|
||||
);
|
||||
return boost::none;
|
||||
}
|
||||
}
|
||||
|
||||
const char *env_rpc_login = nullptr;
|
||||
const bool has_rpc_arg = command_line::has_arg(vm, arg.rpc_login);
|
||||
|
||||
@@ -52,6 +52,9 @@ namespace cryptonote
|
||||
descriptors& operator=(descriptors&&) = delete;
|
||||
|
||||
const command_line::arg_descriptor<std::string> rpc_bind_ip;
|
||||
const command_line::arg_descriptor<std::string> rpc_bind_ipv6_address;
|
||||
const command_line::arg_descriptor<bool> rpc_use_ipv6;
|
||||
const command_line::arg_descriptor<bool> rpc_require_ipv4;
|
||||
const command_line::arg_descriptor<std::string> rpc_login;
|
||||
const command_line::arg_descriptor<bool> confirm_external_bind;
|
||||
const command_line::arg_descriptor<std::string> rpc_access_control_origins;
|
||||
@@ -76,6 +79,9 @@ namespace cryptonote
|
||||
static boost::optional<epee::net_utils::ssl_options_t> process_ssl(const boost::program_options::variables_map& vm, const bool any_cert_option = false);
|
||||
|
||||
std::string bind_ip;
|
||||
std::string bind_ipv6_address;
|
||||
bool use_ipv6;
|
||||
bool require_ipv4;
|
||||
std::vector<std::string> access_control_origins;
|
||||
boost::optional<tools::login> login; // currently `boost::none` if unspecified by user
|
||||
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled;
|
||||
|
||||
@@ -247,7 +247,9 @@ namespace tools
|
||||
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<wallet_rpc_server, connection_context>::init(
|
||||
rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login),
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user