mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-12 21:02:38 -03:00
0d64b8f709
While limitations on the influence of attackers on addrman already exist (affected buckets are restricted to a subset based on incoming IP / network group), there is no reason to permit them to let them feed us addresses at more than a multiple of the normal network rate. This commit introduces a "token bucket" rate limiter for the processing of addresses in incoming ADDR and ADDRV2 messages. Every connection gets an associated token bucket. Processing an address in an ADDR or ADDRV2 message from non-whitelisted peers consumes a token from the bucket. If the bucket is empty, the address is ignored (it is not forwarded or processed). The token counter increases at a rate of 0.1 tokens per second, and will accrue up to a maximum of 1000 tokens (the maximum we accept in a single ADDR or ADDRV2). When a GETADDR is sent to a peer, it immediately gets 1000 additional tokens, as we actively desire many addresses from such peers (this may temporarily cause the token count to exceed 1000). The rate limit of 0.1 addr/s was chosen based on observation of honest nodes on the network. Activity in general from most nodes is either 0, or up to a maximum around 0.025 addr/s for recent Bitcoin Core nodes. A few (self-identified, through subver) crawler nodes occasionally exceed 0.1 addr/s.
89 lines
3.3 KiB
C++
89 lines
3.3 KiB
C++
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <netaddress.h>
|
|
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
#ifndef BITCOIN_NET_PERMISSIONS_H
|
|
#define BITCOIN_NET_PERMISSIONS_H
|
|
|
|
struct bilingual_str;
|
|
|
|
extern const std::vector<std::string> NET_PERMISSIONS_DOC;
|
|
|
|
enum class NetPermissionFlags : uint32_t {
|
|
None = 0,
|
|
// Can query bloomfilter even if -peerbloomfilters is false
|
|
BloomFilter = (1U << 1),
|
|
// Relay and accept transactions from this peer, even if -blocksonly is true
|
|
// This peer is also not subject to limits on how many transaction INVs are tracked
|
|
Relay = (1U << 3),
|
|
// Always relay transactions from this peer, even if already in mempool
|
|
// Keep parameter interaction: forcerelay implies relay
|
|
ForceRelay = (1U << 2) | Relay,
|
|
// Allow getheaders during IBD and block-download after maxuploadtarget limit
|
|
Download = (1U << 6),
|
|
// Can't be banned/disconnected/discouraged for misbehavior
|
|
NoBan = (1U << 4) | Download,
|
|
// Can query the mempool
|
|
Mempool = (1U << 5),
|
|
// Can request addrs without hitting a privacy-preserving cache, and send us
|
|
// unlimited amounts of addrs.
|
|
Addr = (1U << 7),
|
|
|
|
// True if the user did not specifically set fine grained permissions
|
|
Implicit = (1U << 31),
|
|
All = BloomFilter | ForceRelay | Relay | NoBan | Mempool | Download | Addr,
|
|
};
|
|
static inline constexpr NetPermissionFlags operator|(NetPermissionFlags a, NetPermissionFlags b)
|
|
{
|
|
using t = typename std::underlying_type<NetPermissionFlags>::type;
|
|
return static_cast<NetPermissionFlags>(static_cast<t>(a) | static_cast<t>(b));
|
|
}
|
|
|
|
class NetPermissions
|
|
{
|
|
public:
|
|
NetPermissionFlags m_flags;
|
|
static std::vector<std::string> ToStrings(NetPermissionFlags flags);
|
|
static inline bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
|
|
{
|
|
using t = typename std::underlying_type<NetPermissionFlags>::type;
|
|
return (static_cast<t>(flags) & static_cast<t>(f)) == static_cast<t>(f);
|
|
}
|
|
static inline void AddFlag(NetPermissionFlags& flags, NetPermissionFlags f)
|
|
{
|
|
flags = flags | f;
|
|
}
|
|
//! ClearFlag is only called with `f` == NetPermissionFlags::Implicit.
|
|
//! If that should change in the future, be aware that ClearFlag should not
|
|
//! be called with a subflag of a multiflag, e.g. NetPermissionFlags::Relay
|
|
//! or NetPermissionFlags::Download, as that would leave `flags` in an
|
|
//! invalid state corresponding to none of the existing flags.
|
|
static inline void ClearFlag(NetPermissionFlags& flags, NetPermissionFlags f)
|
|
{
|
|
assert(f == NetPermissionFlags::Implicit);
|
|
using t = typename std::underlying_type<NetPermissionFlags>::type;
|
|
flags = static_cast<NetPermissionFlags>(static_cast<t>(flags) & ~static_cast<t>(f));
|
|
}
|
|
};
|
|
|
|
class NetWhitebindPermissions : public NetPermissions
|
|
{
|
|
public:
|
|
static bool TryParse(const std::string& str, NetWhitebindPermissions& output, bilingual_str& error);
|
|
CService m_service;
|
|
};
|
|
|
|
class NetWhitelistPermissions : public NetPermissions
|
|
{
|
|
public:
|
|
static bool TryParse(const std::string& str, NetWhitelistPermissions& output, bilingual_str& error);
|
|
CSubNet m_subnet;
|
|
};
|
|
|
|
#endif // BITCOIN_NET_PERMISSIONS_H
|