mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-04 10:07:27 -05:00
b691f2df5f
This patch improves performance and resource usage around IP addresses that are banned for misbehavior. They're already not actually banned, as connections from them are still allowed, but they are preferred for eviction if the inbound connection slots are full. Stop treating these like manually banned IP ranges, and instead just keep them in a rolling Bloom filter of misbehaving nodes, which isn't persisted to disk or exposed through the ban framework. The effect remains the same: preferred for eviction, avoided for outgoing connections, and not relayed to other peers. Also change the name of this mechanism to better reflect reality; they're not banned, just discouraged. Contains release notes and several interface improvements by John Newbery.
90 lines
3.7 KiB
C++
90 lines
3.7 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// 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.
|
|
#ifndef BITCOIN_BANMAN_H
|
|
#define BITCOIN_BANMAN_H
|
|
|
|
#include <addrdb.h>
|
|
#include <bloom.h>
|
|
#include <fs.h>
|
|
#include <net_types.h> // For banmap_t
|
|
#include <sync.h>
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
// NOTE: When adjusting this, update rpcnet:setban's help ("24h")
|
|
static constexpr unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban
|
|
// How often to dump addresses to banlist.dat
|
|
static constexpr std::chrono::minutes DUMP_BANS_INTERVAL{15};
|
|
|
|
class CClientUIInterface;
|
|
class CNetAddr;
|
|
class CSubNet;
|
|
|
|
// Banman manages two related but distinct concepts:
|
|
//
|
|
// 1. Banning. This is configured manually by the user, through the setban RPC.
|
|
// If an address or subnet is banned, we never accept incoming connections from
|
|
// it and never create outgoing connections to it. We won't gossip its address
|
|
// to other peers in addr messages. Banned addresses and subnets are stored to
|
|
// banlist.dat on shutdown and reloaded on startup. Banning can be used to
|
|
// prevent connections with spy nodes or other griefers.
|
|
//
|
|
// 2. Discouragement. If a peer misbehaves enough (see Misbehaving() in
|
|
// net_processing.cpp), we'll mark that address as discouraged. We still allow
|
|
// incoming connections from them, but they're preferred for eviction when
|
|
// we receive new incoming connections. We never make outgoing connections to
|
|
// them, and do not gossip their address to other peers. This is implemented as
|
|
// a bloom filter. We can (probabilistically) test for membership, but can't
|
|
// list all discouraged addresses or unmark them as discouraged. Discouragement
|
|
// can prevent our limited connection slots being used up by incompatible
|
|
// or broken peers.
|
|
//
|
|
// Neither banning nor discouragement are protections against denial-of-service
|
|
// attacks, since if an attacker has a way to waste our resources and we
|
|
// disconnect from them and ban that address, it's trivial for them to
|
|
// reconnect from another IP address.
|
|
//
|
|
// Attempting to automatically disconnect or ban any class of peer carries the
|
|
// risk of splitting the network. For example, if we banned/disconnected for a
|
|
// transaction that fails a policy check and a future version changes the
|
|
// policy check so the transaction is accepted, then that transaction could
|
|
// cause the network to split between old nodes and new nodes.
|
|
|
|
class BanMan
|
|
{
|
|
public:
|
|
~BanMan();
|
|
BanMan(fs::path ban_file, CClientUIInterface* client_interface, int64_t default_ban_time);
|
|
void Ban(const CNetAddr& net_addr, const BanReason& ban_reason, int64_t ban_time_offset = 0, bool since_unix_epoch = false);
|
|
void Ban(const CSubNet& sub_net, const BanReason& ban_reason, int64_t ban_time_offset = 0, bool since_unix_epoch = false);
|
|
void ClearBanned();
|
|
int IsBannedLevel(CNetAddr net_addr);
|
|
bool IsBanned(CNetAddr net_addr);
|
|
bool IsBanned(CSubNet sub_net);
|
|
bool Unban(const CNetAddr& net_addr);
|
|
bool Unban(const CSubNet& sub_net);
|
|
void GetBanned(banmap_t& banmap);
|
|
void DumpBanlist();
|
|
|
|
private:
|
|
void SetBanned(const banmap_t& banmap);
|
|
bool BannedSetIsDirty();
|
|
//!set the "dirty" flag for the banlist
|
|
void SetBannedSetDirty(bool dirty = true);
|
|
//!clean unused entries (if bantime has expired)
|
|
void SweepBanned();
|
|
|
|
RecursiveMutex m_cs_banned;
|
|
banmap_t m_banned GUARDED_BY(m_cs_banned);
|
|
bool m_is_dirty GUARDED_BY(m_cs_banned);
|
|
CClientUIInterface* m_client_interface = nullptr;
|
|
CBanDB m_ban_db;
|
|
const int64_t m_default_ban_time;
|
|
CRollingBloomFilter m_discouraged GUARDED_BY(m_cs_banned) {50000, 0.000001};
|
|
};
|
|
|
|
#endif
|