mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 07:31:35 +02:00
p2p, rpc: group public IPv6 connection limits by /64
(cherry picked from commit f277d328cf1f7e64423b5eb7dc0e21649f71e47a)
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include "net_utils_base.h"
|
||||
#include "http_auth.h"
|
||||
#include "http_base.h"
|
||||
#include "syncobj.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
|
||||
@@ -65,6 +66,9 @@ namespace net_utils
|
||||
critical_section m_lock;
|
||||
};
|
||||
|
||||
// RPC limits groupable IPv6 clients by /64 to avoid per-address limit bypasses.
|
||||
std::string get_rpc_connection_limit_key(const net_utils::network_address& address);
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace net_utils
|
||||
CRITICAL_REGION_LOCAL(m_config.m_lock);
|
||||
if (m_config.m_connection_count)
|
||||
--m_config.m_connection_count;
|
||||
auto elem = m_config.m_connections.find(m_conn_context.m_remote_address.host_str());
|
||||
auto elem = m_config.m_connections.find(get_rpc_connection_limit_key(m_conn_context.m_remote_address));
|
||||
if (elem != m_config.m_connections.end())
|
||||
{
|
||||
if (elem->second == 1 || elem->second == 0)
|
||||
@@ -243,7 +243,7 @@ namespace net_utils
|
||||
bool simple_http_connection_handler<t_connection_context>::after_init_connection()
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_config.m_lock);
|
||||
++m_config.m_connections[m_conn_context.m_remote_address.host_str()];
|
||||
++m_config.m_connections[get_rpc_connection_limit_key(m_conn_context.m_remote_address)];
|
||||
++m_config.m_connection_count;
|
||||
m_initialized = true;
|
||||
return true;
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace epee
|
||||
return true;
|
||||
|
||||
const bool is_private = na.is_loopback() || na.is_local();
|
||||
const auto elem = config.m_connections.find(na.host_str());
|
||||
const auto elem = config.m_connections.find(net_utils::http::get_rpc_connection_limit_key(na));
|
||||
if (elem != config.m_connections.end())
|
||||
{
|
||||
if (is_private)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
#include <cstddef>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
#include "byte_slice.h"
|
||||
@@ -208,6 +209,9 @@ namespace net_utils
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
bool should_group_ipv6_by_prefix(const boost::asio::ip::address_v6& ip);
|
||||
boost::asio::ip::address_v6 get_ipv6_subnet_address(const boost::asio::ip::address_v6& ip, const std::size_t prefix_bits);
|
||||
|
||||
inline bool operator==(const ipv6_network_address& lhs, const ipv6_network_address& rhs) noexcept
|
||||
{ return lhs.equal(rhs); }
|
||||
inline bool operator!=(const ipv6_network_address& lhs, const ipv6_network_address& rhs) noexcept
|
||||
|
||||
@@ -31,7 +31,7 @@ set(EPEE_INCLUDE_DIR_BASE "${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
||||
# Add headers to the file list, to be able to search for them and autosave in IDEs.
|
||||
monero_find_all_headers(EPEE_HEADERS_PUBLIC "${EPEE_INCLUDE_DIR_BASE}")
|
||||
|
||||
monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp parserse_base_utils.cpp
|
||||
monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp http_protocol_handler.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp parserse_base_utils.cpp
|
||||
wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
|
||||
int-util.cpp portable_storage.cpp
|
||||
misc_language.cpp
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2026, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "net/http_protocol_handler.h"
|
||||
|
||||
namespace epee { namespace net_utils { namespace http
|
||||
{
|
||||
std::string get_rpc_connection_limit_key(const net_utils::network_address& address)
|
||||
{
|
||||
if (address.get_type_id() == net_utils::ipv6_network_address::get_type_id())
|
||||
{
|
||||
const boost::asio::ip::address_v6 ip = address.as<const net_utils::ipv6_network_address>().ip();
|
||||
if (net_utils::should_group_ipv6_by_prefix(ip))
|
||||
return net_utils::get_ipv6_subnet_address(ip, 64).to_string() + "/64";
|
||||
}
|
||||
|
||||
return address.host_str();
|
||||
}
|
||||
}}}
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#include "net/net_utils_base.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
|
||||
#include "string_tools.h"
|
||||
@@ -45,6 +47,34 @@ namespace epee { namespace net_utils
|
||||
bool ipv6_network_address::is_loopback() const { return m_address.is_loopback(); }
|
||||
bool ipv6_network_address::is_local() const { return m_address.is_link_local(); }
|
||||
|
||||
static bool is_ipv6_unique_local(const boost::asio::ip::address_v6& ip)
|
||||
{
|
||||
const boost::asio::ip::address_v6::bytes_type bytes = ip.to_bytes();
|
||||
return (bytes[0] & 0xfe) == 0xfc;
|
||||
}
|
||||
|
||||
bool should_group_ipv6_by_prefix(const boost::asio::ip::address_v6& ip)
|
||||
{
|
||||
return !ip.is_unspecified() && !ip.is_loopback() && !ip.is_multicast() &&
|
||||
!ip.is_link_local() && !ip.is_site_local() && !is_ipv6_unique_local(ip) &&
|
||||
!ip.is_v4_mapped();
|
||||
}
|
||||
|
||||
boost::asio::ip::address_v6 get_ipv6_subnet_address(const boost::asio::ip::address_v6& ip, const std::size_t prefix_bits)
|
||||
{
|
||||
boost::asio::ip::address_v6::bytes_type bytes = ip.to_bytes();
|
||||
const std::size_t bits = std::min(prefix_bits, std::size_t{128});
|
||||
if (bits < 128)
|
||||
{
|
||||
const std::size_t full_bytes = bits / 8;
|
||||
const std::size_t remainder_bits = bits % 8;
|
||||
if (remainder_bits != 0)
|
||||
bytes[full_bytes] &= uint8_t(0xffu << (8 - remainder_bits));
|
||||
std::fill(bytes.begin() + full_bytes + (remainder_bits != 0), bytes.end(), 0);
|
||||
}
|
||||
return boost::asio::ip::address_v6(bytes);
|
||||
}
|
||||
|
||||
|
||||
bool ipv4_network_subnet::equal(const ipv4_network_subnet& other) const noexcept
|
||||
{ return is_same_host(other) && m_mask == other.m_mask; }
|
||||
|
||||
Reference in New Issue
Block a user